Reputation: 1411
The following code compiles with gcc and clang (and many other C++11 compilers)
#include <stdint.h>
typedef int datatype;
template <typename T>
struct to_datatype {};
template <>
struct to_datatype<int16_t> {
static constexpr datatype value = 1;
};
template <typename T>
class data {
public:
data(datatype dt = to_datatype<T>::value) {}
};
int main() {
data<char> d{to_datatype<int16_t>::value};
}
when compile with (almost) latest MSVC
> cl .\test.cpp /std:c++latest /permissive-
Microsoft (R) C/C++ Optimizing Compiler Version 19.24.28314 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
test.cpp
.\test.cpp(16): error C2039: 'value': is not a member of 'to_datatype<T>'
with
[
T=char
]
.\test.cpp(16): note: see declaration of 'to_datatype<T>'
with
[
T=char
]
.\test.cpp(20): note: see reference to class template instantiation 'data<char>' being compiled
Is this a bug of MSVC? If yes, which term in C++ standard best describe it?
If you replace part of the code with
template <typename T>
class data {
public:
data(datatype dt) {}
data() : data(to_datatype<T>::value) {}
};
it compiles smoothly anyway.
Upvotes: 13
Views: 633
Reputation: 22152
I would say MSVC is wrong not to accept the code.
According to [dcl.fct.default]/5 of the C++17 standard final draft, name lookup in default arguments of a member function of a class template is done according to the rules in [temp.inst].
According to [temp.inst]/2 implicit instantiation of a class template does not cause instantiation of default arguments of member functions and according to [temp.inst]/4 a default argument for a member function of a (non-explicit specialization of a) class template is instantiated when it is used by a call.
There is no call using the default argument to_datatype<T>::value
in your code and so it should not be instantiated. Therefore there shouldn't be an error about lookup of value
in to_datatype<char>
failing.
(The relevant sections in the C++11 standard final draft have equivalent wording, except for numbering, see [decl.fct.default]/5, [temp.inst]/1 and [temp.inst]/3 instead.)
Upvotes: 8