Reputation: 247969
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:
I've reproduced the problem on VC++ 2010 and 2012.
Upvotes: 12
Views: 654
Reputation:
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>
Upvotes: 3