Search code examples
c++templatesvisual-studio-2012visual-studio-2013compiler-bug

Template argument and its own template argument both contain identically-named types; how can I reference the second in a function signature?


Consider this code:

template<typename T>
struct Foo
{
    typedef T t_type;
};

template<typename T>
struct Bar
{
    typedef T t_type; 
};

template<typename U>
auto f() -> typename U::t_type::t_type
{
    return typename U::t_type::t_type();
}

int main(int, char**)
{
    typedef Foo<Bar<int>> Baz;
    f<Baz>();
}

It doesn't compile under VS2012:

invalid explicit template argument(s) for 'U::t_type::{ctor} f(void)'

Seemingly, the compiler is concluding that the second t_type in typename U::t_type::t_type is naming a constructor rather than an identically-named nested type. Is there anything I can do to help clarify the situation?


Solution

  • First you're missing a typename keyword

    template<typename U>
    auto f() -> typename U::t_type::t_type
    {
        return typename U::t_type::t_type();
    }
    

    and main should have arguments (int,char**).

    That said..

    this has already been reported and apparently fixed ([will be/has been] shipped in an unspecified "future version"). MSVC 2013 update 4 is also affected.

    The proposed workaround is:

    template<typename T>
    struct Foo
    {
        typedef T t_type;
    };
    
    template<typename T>
    struct Bar
    {
        typedef T t_type;
    };
    
    template<typename U>
    auto f() -> typename U::t_type::template t_type
                                    ^^^^^^^^
    {
        return typename U::t_type::t_type();
    }
    
    int main(int, char**)
    {
        typedef Foo<Bar<int>> Baz;
        f<Baz>();
    }
    

    although if you use the code above everything proceeds as in the following image:

    enter image description here