gcc doesn't accept out-of-line definition of member with non-type template parameter defined via nested templated using clause

戏子无情 提交于 2021-02-19 04:07:51

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!