Why does MSVC fail to compile this template function?

c++, templates, visual-c++

Solution

After running a few tests myself, this seems to be a compiler bug in MSVC. While it works fine with GCC, MSVC gives cryptic and unhelpful compiler error (identical to the ones in your question) when you attempt to use `traits<T>::val` inside the template parameters for the `S< E e >` return.

The funny thing is, when you change `S< E e >` to take an integer instead, it works. Consider this example, identical to yours with some different naming:

enum E {
    x
};

template <typename T>
struct traits {
    static const E val = x;
};

template <E e>
struct S {
    S(){};
};

template <typename T>
S< traits<T>::val > tricky(T t) {
    return S< traits<T>::val > ();
};

int main() {
    char thiskidwhowalksaround = 0;
    S<x> s = tricky( thiskidwhowalksaround );
}

Now, let's just change one single thing:

template <int e> // int instead of E
struct S {
    S(){};
};

The program then compiles (links, and runs) flawlessly for me. If you also revert back to the original, and then pass in a value of `E` directly, like:

template <typename T>
S< x > tricky(T t) { 
// ^ here
    return S< x > (); // <-- here
};

Then the program compiles file. MSVC has the issue where it bites the dust at trying to do the following:

`traits<T>::val`

where `val` is any kind of enumeration. I'm 99% certain this is a deficiency in the Compiler itself. This seems to be perfectly well-formed C++ so I can't say that GCC is doing something wrong or extension-y by having the original code snippet work. Thus, the best I can glean is that MSVC is lacking in compiler robustness compared to its peers, yet again.

You can stop reading here, because now I'm going to take a small moment to rant about the MSVC compiler.

`begin<rant>` It's not that the VC++ team is bad or that C++ is bad, but from what I glean the compiler team and the standard library teams at Microsoft -- as of time of writing -- are tiny compared to other departments. It irks me that such a fundamental and important language and part of the core of MS's industry has such comparatively little manpower that it cannot keep up with what - in my short lifetime - I find to be one of the slowest moving standards in the world. I certainly am not knocking the individuals that work on the VC++ team, but I'm deeply perplexed as to why there are not more of them working on bringing C++ not only up to speed but making the compiler work better and as good as its other product areas. `end<rant>`

Problem

I ran into a problem porting some code to MSVC, which puzzles me. As far as I know, the code should be legal, and Clang compiles it just fine. I've narrowed it down to the following: ``` enum E { x }; template <typename T> struct traits { static const E val = x; }; template <E e> struct S { S(){}; }; template <typename T> S<traits<T>::val> foo(T t); int main() { char c = 0; foo(c); } ``` Note that after compilation, the code is expected to yield a linker error (I stripped away the definition of the function `foo` to keep the sample minimal), but it should compile cleanly as far as I know. However, MSVC gives me this error: error C2893: Failed to specialize function template 'S::val> foo(T)' So my question: - is MSVC by any chance correct in rejecting the code? (and if so, why?) - if not, can anyone narrow down what it is doing wrong? As in, is it a language feature they don't implement at all (such as two-phase name lookup for templates), or "just" a plain bug in their implementation of a feature they claim to support? I've reproduced the problem on VC++ 2010 and 2012.

Original source

Related problems