I have a trait class that associates types to integer values.
struct traits
{
private:
template<int ID> struct type_impl {};
template<> struct type_impl<1> { using type = int; };
// ...
public:
template<int ID> using type = typename type_impl<ID>::type;
};
I am writing a template function which return type is provided by the traits class above and specialize it for various int values:
template<int ID> traits::type<ID> function();
template<> inline traits::type<1> function<1>() { return 42; };
// ...
This compiles fine with VS2015 (see https://godbolt.org/z/LpZnni) but not with VS2017 that complains that:
error C2912: explicit specialization 'int function<1>(void)' is not a specialization of a function template
To my surprise, declaring a non template function like below compiles:
traits::type<1> other_function();
Making traits::type_impl
public solves the compilation problem but I don't understand why. To me either both the specialization and the declaration of other_function
should compile with traits::type_impl
private or none.
Thank you for your help.
Further investigation following @rubenvb 's comment I understand that the code I posted is illegal, so I tried making partial specialization instead (which I believe is legal):
struct traits
{
private:
template<int ID,bool=true> struct type_impl {};
template<bool B> struct type_impl<1,B> { using type = int; };
// ...
public:
template<int ID> using type = typename type_impl<ID>::type;
};
template<int ID> traits::type<ID> function();
template<> inline traits::type<1> function<1>() { return 42; };
Now every compiler is happy but VS2017 that still wants traits::type_impl
public. I guess that's a Visual Studio bug.