Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keyword 'template' confuses MSVC

One of those "which compiler is right" questions about templates. Consider following:

template<typename T>
class Container
{
public:
    template<typename V>
    class iterator;
};

template<typename T>
template<typename V>
class Container<T>::iterator
{
public:
    iterator &operator++();
};

Now when providing a definition for the operator++ out-of-line it would look like this:

template<typename T>
template<typename V>
typename Container<T>::template iterator<V> &Container<T>::iterator<V>::operator++()
{
    //do your thing
    return *this;
}

And sure enough pretty much any version of GCC from 4.8+ and Clang 3.2+ can compile it. MSVC19+ however does not and it specifically dislikes the template keyword in that definition. It complains that it cannot match the declaration and definition which is especially funny since it gives what it looked for and the "candidate" and they are both identical. If template is removed so only typename Container<T>::iterator<V> is used, MSVC compiles it just fine. Clang and GCC however will fail.

You can try it live at Compiler Explorer: live demo

So who is right? Since both GCC and Clang has this for a long time I tend to lean towards them. However I would like to support all three. So either I move it to in-class definition or use #ifdef? Seems wrong and if MSVC is at wrong here it should be reported (unless it is a known issue).

like image 788
Resurrection Avatar asked Feb 15 '18 18:02

Resurrection


Video Answer


1 Answers

You can simplify code by using trailing return type. No need for typename or template:

template<typename T>
template<typename V>
auto Container<T>::iterator<V>::operator++() -> iterator<V> &
{
    //do your thing
    return *this;
}

online compiler

like image 79
user7860670 Avatar answered Oct 24 '22 23:10

user7860670