trick with type_identity_t

Hi,

I do not understand the following code:

1
2
3
4
5
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:


1
2
3
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
try https://en.cppreference.com/w/cpp/types/type_identity

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:
1
2
using my_array = T[];
my_array{ t1, t2, t3 }; // ok 
Incidentally
 
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.
https://eel.is/c++draft/expr.type.conv

See an equivalent trick used here:
https://cplusplus.com/forum/general/207656/#msg979820
Where the type alias left_to_right is needed to satisfy the compiler for the same reason.
Last edited on
Registered users can post here. Sign in or register to post.