4

My question is about the following piece of code:

    template <class...T>
    class A
    {
    public:
        template <class...S>
        static void a() { }
    };

    template <class...T>
    class B
    {
    public:
        template <class...S>
        void b()
        {
            A<T...>::a<S...>();
        }
    };

    int main(int argc, char** argv)
    {
        return 0;
    }

I have a class A that has a variadic template and contains a static method a that has another variadic template. From somewhere else (class B in this case) I have two different sets of variadic templates I want to pass to A::a.

The compiler (GCC 4.8.1) gives the following error message:

    main.cpp: In static member function ‘static void B<T>::b()’:
    main.cpp:16:22: error: expected primary-expression before ‘...’ token
             A <T...>::a<S...>();
                          ^
    main.cpp:16:22: error: expected ‘;’ before ‘...’ token

Also notice that when I change the method b() to this:

        void b()
        {
            A<int, char, short>::a<S...>();
        }

or some other specification of A's templates then the code compiles just fine.

What is wrong with the above code?

user1286875
  • 193
  • 1
  • 6
  • 1
    possible duplicate of [Where and why do I have to put the "template" and "typename" keywords?](http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords) – jrok Jul 23 '13 at 17:53
  • Note that things get particularly funky when you expand boths packs in one expression: they get expanded in lockstep – sehe Jul 23 '13 at 17:54
  • @sehe this is two separate pack expansions, not a single pattern expanding two packs simultaneously (e.g., `f(A::a()...)`). So the expansions are independent. – Casey Jul 23 '13 at 17:57
  • @Casey I know, right. This is why it's a comment – sehe Jul 23 '13 at 17:58

1 Answers1

6

add template here

A<T...>::template a<S...>();

see comment for reason. Also this compile nicely on VC++ without the keyword so I guess it is compiler dependent.

yngccc
  • 5,594
  • 2
  • 23
  • 33
  • 1
    VC++ doesn't implement two-phase name lookup in templates; it effectively treats every name as a dependent name. – Casey Jul 23 '13 at 18:00
  • 1
    Or to be more clear: MSVC violates the standard by not requiring `template` there. It should treat `A::a` as a value, then treat `<` as less than, then have a parsing error when you put `S...` on the right-hand-side of a `<` expression. The idea is that errors can be found in `template` prior to instantiating them: MSVC fails to find entire categories of errors, so it doesn't need the `template` disambiguator. – Yakk - Adam Nevraumont Jul 23 '13 at 19:12