问题
The title seems convoluted but our test-case is actually a minimal example for a real case.
We have code for which we want to choose implementation of a method based on the template parameter. We during clean up we defined conditional enable_if_t
with using clause, and as next step wanted to put definition out of line, this produced following code:
#include <type_traits>
#include <iostream>
#include <string>
template <typename T>
struct A {
template <typename U>
using is_int_or_float = std::enable_if_t< std::is_same<U, int>::value || std::is_same<U, float>::value >;
template<typename U = T, is_int_or_float<U>* = nullptr >
void f();
template<typename U = T, typename std::enable_if_t< std::is_same<U,std::string>::value >* = nullptr >
void f();
};
template <typename T>
template <typename U, typename A<T>::template is_int_or_float<U>* >
void A<T>::f(){
std::cout << "f for int or float\n";
}
template <typename T>
template<typename U, typename std::enable_if_t< std::is_same<U,std::string>::value >*>
void A<T>::f() {
std::cout << "f for string\n";
}
int main () {
A<int> a_int;
A<std::string> a_string;
A<float> a_float;
a_int.f();
a_string.f();
a_float.f();
a_float.f<std::string>();
return 0;
}
Gcc does not accept it while clang does: https://godbolt.org/g/Gfm1tw
gcc (and icc) complain that there is no valid prototype for method defined with is_int_or_float
.
I am not sure whether clang is too promiscuous or gcc should be able to get past the dependent type.
The code works if we switchtypename A<T>::template is_int_or_float<U>
for it's definition:
template <typename T>
template <typename U, std::enable_if_t< std::is_same<U, int>::value || std::is_same<U, float>::value >* >
void A<T>::f(){
std::cout << "f for int or float\n";
}
Does using using
change some rules about type matching, or should gcc be able to consume it?
EDIT: Thanks to input from @VTT we figured out, that the difference is in the typename
keyword in the out-of-line declaration typename A<T>::template is_int_or_float<U>*
. Removing it makes gcc compile and clang refuse the code.
So the question can be rephrased and simplified: Is typename required or this allowed in this case?
来源:https://stackoverflow.com/questions/48448353/gcc-doesnt-accept-out-of-line-definition-of-member-with-non-type-template-param