Reputation: 372
The following code compiles, but will not work:
template<typename T>
struct Nesting
{
template<typename U>
struct _Nested
{
};
template<typename U>
using Nested = _Nested<U>;
};
template<typename T>
struct F
{
static constexpr bool is_my_nested_class = false;
};
template<typename T, typename U>
struct F<typename Nesting<T>::Nested<U>>
{
static constexpr bool is_my_nested_class = true;
};
I create these Nesting and Nested types and try to uses a type trait pattern on it. It compiles (using MSVC 2014 w/ CPP11), but
F<Nesting<int>::Nested<long>>::is_my_nested_class
returns false.
Is this forbidden or undefined by the standard ? What rule does it break ? Any workaround ?
Thank you very much!
Upvotes: 4
Views: 613
Reputation: 20631
Your nested alias could refer to any type, particularly in a specialisation:
template<typename T>
struct Nesting
{
template<typename U>
struct _Nested
{
};
template<typename U>
using Nested = _Nested<U>;
};
// Consider this specialisation:
template<>
struct Nesting<int>
{
template<typename U>
using Nested = float;
};
Now, clearly F<Nesting<int>::Nested<int>>::is_my_nested_class
should be the same as F<float>::is_my_nested_class
, however, how can the compiler deduce this for the latter case? That is, if I wrote:
static_assert(F<float>::is_my_nested_class, "not nested");
The compiler would need to see that F<float>
is the same as F<Nesting<int>::Nested<int>>
, even though the latter hasn't been instantiated. As it can't reasonably be expected to do so, the case is disallowed.
Upvotes: 1