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

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

我正在尝试在我的一个项目中添加对 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。

谢谢

专业化是一种解决方案:

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;
}

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

当 SFINAE 基于 class 模板的参数创建 class 模板成员函数时,获得正确的代码可能很棘手。 [temp.res]/p8:

If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.

诀窍是让 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() 都有一个有效的专业化。