anon
anon

Reputation: 69

C++17 dependent name is not a type, works in C++14

Consider the following code:

template <typename T>
struct X
{
    void foo(){}
};

class Y { };

template <typename T, typename... U>
class Example {
protected:
    template <template<typename> typename example_t>
    using alias = X<example_t<T>>;

};

template <typename T>
struct ExampleA : public Example<T, Y>
{
    using MyAlias = ExampleA::alias<ExampleA>;
};

In C++14 I could do the following and have it work as expected:

ExampleA<int>::MyAlias test;
test.foo();

A recent upgrade to C++17 now gives a warning 'ExampleA<T>::alias': dependent name is not a type as well as syntax error: identifier 'alias'.

Normally when you get something involving a dependent name it means you need to add the typename keyword as in the following example (iterator is dependent upon std::vector<T>):

template<typename T> 
void bar() {
    /* typename */ std::vector<T>::iterator it;
}

However, I don't believe that to be the case here. Also, using using MyAlias = Example<T, Y>::alias<ExampleA>; results in the same error.

Did a change in C++17 invalidate this code, or is this a compiler bug? What can I do to fix this in C++17?

Upvotes: 3

Views: 381

Answers (1)

Guillaume Racicot
Guillaume Racicot

Reputation: 41770

MSVC ignored the abscence of desambiguators due to an implementation detail of their compiler.

With new advances and reengineering of their compiler, they now implement two phase name lookup as they should. However, with that implemented, it's really hard in some cases to ignore absence of desambiguators.

They became even more strict with the /permissive- flag, which is an attempt to disable most of their extensions due to their previous lack of two phase name lookup.

Your code snippet look like this with desambiguators:

template <typename T>
struct ExampleA : public Example<T, Y>
{
    using MyAlias = typename ExampleA::template alias<ExampleA>;
};

See it as an opportunity to upgrade the compilance and portability of your code.

However with C++20, many cases where desambigurator were needed are now optional:

template<typename T>
auto wrapper() -> T::type; // no typename!

Upvotes: 7

Related Questions