trick with type_identity_t


I do not understand the following code:

template<typename From, typename To>
concept ConvertsWithoutNarrowing = requires (From && x)
	std::type_identity_t<To[]>{std::forward<From>(x) } -> std::same_as<To[1]>;

What does type_identity_t do??

Look at this code:

double x;
std::vector<int> coll;
auto res = std::type_identity_t<decltype(coll)>{std::forward<double>(x)};

It throws this error:

Element '1': conversion from '_Ty' to '_Ty' requires a narrowing conversion

Last edited on

as to what this is trying to do, I honestly do not know. Its name says it wants to do a type conversion without narrowing, but I have only tried the most basic of concepts and there must be something more to this than I can understand.
type_identity_t<To[]> is used here to satisfy an arbitrary restriction in the C++ language grammar.

The problem is that you can't make temporary arrays with a syntax like
T[]{ t1, t2, t3 }; // wrong 

But you can get away with it when you spell T[] in a different way:
using my_array = T[];
my_array{ t1, t2, t3 }; // ok 
std::type_identity_t<T[]>{ t1, t2, t3 }; // ok 
works too.

More specifically, the intent is to use [expr.type.conv] to construct an object whose type is To[]. Ideally one could simply write To[]{ std::forward<From>(x) } but that doesn't work because grammatically To[] is neither a typedef-name nor a simple-type-specifier as the standard requires.

The workaround relies on that type_identity_t<To[]> is the same type as To[] but grammatically it is a typedef-name and so the compiler accepts it.

See an equivalent trick used here:
Where the type alias left_to_right is needed to satisfy the compiler for the same reason.
Last edited on
Topic archived. No new replies allowed.