Is it possible to enumerate a list of types to which a type can be converted to? Or would this require a technique similar to static reflection?
struct a {
operator int() const
{ return i; }
explicit operator float() const
{ return f; }
int i;
float f;
};
// enumerated type list for type 'a': tuple<int, float>
One of the things I would like to be able to do—which is related to this but with a somewhat narrower scope—is to check if a type is convertible to, let's say, an integral type, without having to explicitly list them.
The only way I'm able to do this now, is to create a tuple-like type-list of all those integer types, throw it in std::is_convertible and expand them within a std::conjunction. But I would really prefer to use a way which doesn't require me write out all the types of a specific type class. I'm specifically looking for a solution that is compatible with C++17 but if that is not possible or is simply too cumbersome, a C++20 solution is acceptable too.
The first part of my question seems to be well answered by Igor Tandetnik and Barry. Enumerating all of the types to which a type can be converted to would be undesirable for the reasons they have laid out. Enumerating the non-templated user-defined converion operators of a type could be useful but that would require someting like static reflection, which isn't possible for the time being.
Regarding the second part of my question, it seems that there are some nuances involved with type conversions between arithmetic types. Since they are all convertible to each other, finding the type trait that fits my needs maybe requires a different approach. I've decided to list a couple examples to better describe the requirements of this type trait.
#include <type_traits>
#include <utility>
struct a {
operator int() const
{ return i; }
explicit operator float() const
{ return f; }
int i;
float f;
};
// this succeeds, but instead of explicitly writing out 'int' I would like to
// express my intent and write someting as 'any_integral_type' (note: I
// understand that integral types might be too narrow to properly detect,
// so 'any_arithmetic_type' could be acceptable too) and I would
// like to do so without listing all of the integral types by hand
static_assert(std::is_convertible_v<a, int>);
struct b {
int i;
float f;
};
// the difference between type 'a' and type 'b' seems rather obvious and
// I would like to have a type trait that can express that. how to write
// 'assert that b cannot be converted to any type that belongs to the
// std::integral_types' without explicitly writing 'int'?
static_assert(not std::is_convertible_v<b, int>);
// another idea is to use the unary addition operator to force the implicit
// conversion, this way we don't have to be upfront about which type to convert
// to, but this runs into ambiguity issues when there is more than one viable
// conversion operator (e.g.: when operator float isn't marked explicit)
static_assert(std::is_integral_v<decltype(+std::declval<a>())>);