我正在尝试在我的一个项目上添加对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基于类模板的参数来创建类模板成员函数时,获取正确的代码可能会非常棘手。[temp.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()
都有一个有效的专业化。
I'm trying to add support for icc on one of my projects, but I have some issues with SFINAE, when there are more than two methods. Here is a bare simple example of the problem:
#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;
}
This works like a charm with g++ and clang++, but fails to compile with 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)
Is there a workaround for this with icc ? I'd like to avoid changing too much code, I have this problem in several places of my project.
I'm using icc 16.0.2.164.
Thanks
For the code shown in the question, explicitly specializing the member function, as shown in @Jarod42's answer, is probably the simplest.
When SFINAE'ing a class template member function based on parameters of the class template, getting the code correct can be tricky. [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.
The trick is to have the SFINAE expression depend on parameters of the member function template:
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;
}
};
Note that each of the above apply()
s has one valid specialization.