请考虑以下内容:
#include <string>
template <typename T,
typename std::enable_if<(
std::is_integral<T>::value
&& !std::is_same<T, bool>::value
)>::type = 0>
void add(T val)
{
}
void add(bool val)
{
}
void add(const char* val)
{
}
int main()
{
add(true);
add("hi");
add(0);
}
编译器抱怨add(0);
不明确:
[x86-64 clang 6.0.0#1]错误:对“ add”的调用不明确
我想出这一点是因为0
可隐式转换为bool
或const char*
。但是,我希望编译器选择模板方法而不必强制转换0
(即add((int)0);
)或指定模板类型(即add<int>(0);
)。
我还尝试将模板签名更改为:
template <typename T,
typename std::enable_if<(
std::is_integral<T>::value
&& !std::is_same<T, bool>::value
&& !std::is_same<T, unsigned char>::value
)>::type = 0>
void add(T val)
...
但这也无济于事。如何使它按我想要的方式工作?
谢谢!
答案 0 :(得分:4)
enable_if
具有第二个模板参数,默认为void
,并在条件为type
时定义true
。 typename void = 0
无法编译,这就是为什么该函数不能成为重载解析的一部分的原因。但是typename int = 0
确实可以编译,因此传递int
会使函数成为重载重分解的一部分:
template <typename T,
typename std::enable_if<(
std::is_integral<T>::value
&& !std::is_same<T, bool>::value
&& !std::is_same<T, unsigned char>::value
), int>::type = 0>
void add(T val)
{
}
您也可以这样写,而无需传递第二个参数,我认为这更简单:
template <typename T,
typename = typename std::enable_if<(
std::is_integral<T>::value
&& !std::is_same<T, bool>::value
)>::type>
void add(T val)
{
}
void add(bool val)
{
}
void add(const char* val)
{
}
int main()
{
add(true);
add("hi");
add(0); // A
add<int>(0); // B
// A and B call the same function
}