如何使用“英特尔C++编译器”(ICC)在三种方法上使用SFINAE

How to use SFINAE on three methods with Intel C++ Compiler (ICC)?

本文关键字:英特尔 方法 三种 SFINAE 编译器 C++ 何使用 ICC      更新时间:2023-10-16

我正试图在我的一个项目中添加对icc的支持,但当有两个以上的方法时,我对SFINAE有一些问题。这里有一个简单的例子:

#include <iostream>
template<std::size_t Selector>
struct impl {
    template<bool Enable = true, typename std::enable_if<Selector == 1 && Enable, int>::type = 0>
    static void apply(){
        std::cout << "First selector" << std::endl;
    }
    template<bool Enable = true, typename std::enable_if<Selector == 2 && Enable, int>::type = 0>
    static void apply(){
        std::cout << "Second selector" << std::endl;
    }
    template<bool Enable = true, typename std::enable_if<Selector == 3 && Enable, int>::type = 0>
    static void apply(){
        std::cout << "Big selector" << std::endl;
    }
};
int main(){
    impl<1>::apply();
    impl<2>::apply();
    impl<3>::apply();
    return 0;
}

这就像g++和clang++的魅力一样,但无法使用icc:进行编译

test.cpp(16): error: invalid redeclaration of member function template "void impl<Selector>::apply() [with Selector=1UL]" (declared at line 11)
      static void apply(){
                  ^
          detected during instantiation of class "impl<Selector> [with Selector=1UL]" at line 22
test.cpp(11): error: invalid redeclaration of member function template "void impl<Selector>::apply() [with Selector=3UL]" (declared at line 6)
      static void apply(){
                  ^
          detected during instantiation of class "impl<Selector> [with Selector=3UL]" at line 24
compilation aborted for test.cpp (code 2)

icc对此有解决办法吗?我想避免更改太多代码,我在项目的几个地方都有这个问题。

我使用的是icc 16.0.2.164。

感谢

对于问题中显示的代码,显式专门化成员函数可能是最简单的,如@Jarod42的答案所示。

当SFINAE基于类模板的参数来创建类模板成员函数时,要正确获取代码可能很困难。[温度res]/p8:

如果不能为模板生成有效的专门化,并且模板未实例化,模板格式错误,否需要诊断。

诀窍是让SFINAE表达式取决于成员函数模板的参数:

template<std::size_t Selector>
struct impl {
    template<std::size_t S = Selector, typename std::enable_if<S == 1, int>::type = 0>
    static void apply(){
        std::cout << "First selector" << std::endl;
    }
    template<std::size_t S = Selector, typename std::enable_if<S == 2, int>::type = 0>
    static void apply(){
        std::cout << "Second selector" << std::endl;
    }
    template<std::size_t S = Selector, typename std::enable_if<S == 3, int>::type = 0>
    static void apply(){
        std::cout << "Big selector" << std::endl;
    }
};

注意,上述apply()中的每一个都具有一个有效的专门化。

专业化是一种解决方案:

template<std::size_t Selector>
struct impl {
    static void apply();
};
template<>
void impl<1>::apply(){
    std::cout << "First selector" << std::endl;
}
template<>
void impl<2>::apply(){
    std::cout << "Second selector" << std::endl;
}
template<>
void impl<3>::apply(){
    std::cout << "Big selector" << std::endl;
}