我发现了一个有趣的条件函数排除,我是从this site得到的,在测试时我遇到了这个:
#include<type_traits>
namespace detail
{
enum enabler {};
}
template <int overload, typename Condition>
using EnableIf = std::enable_if_t<Condition::value, detail::enabler>;
template <typename T,
EnableIf<0, std::is_same<T, int>>...>
T twice(T t) { return 2 * t; }
template <typename T,
EnableIf<0, std::is_same<T, float>>...>
T twice(T t) { return 2 * t; }
int main()
{
twice(1);
twice(1.f);
return 0;
}
这不应该导致编译器错误,因为EnableIf
类型在两个函数中是相同的吗?我打算为每个重载使用不同的数字,并且有一个模板类,它将包含启动器枚举,以便它是一个不同的类型,但似乎它是不必要的。这是缺陷还是我错过了什么?
我已经在VC ++(2017)和clang上对此进行了测试。
虽然VC ++编译器并没有抱怨,但显然智能感知并不喜欢它:
这就是我的想法,但不管我是否使用不同的整数,它都会抱怨,甚至不会做我说我要做的事情。
答案 0 :(得分:3)
这不应该导致编译器错误,因为
EnableIf
类型在两个函数中是相同的吗?
但他们并不相同。一个需要一包std::enable_if_t<std::is_same<T, int>::value, detail::enabler>
,另一个需要一包std::enable_if_t<std::is_same<T, float>::value, detail::enabler>
。这些是完全不相关的类型,因此您声明了两个不相关的函数模板。实际上,这两种类型中至少有一种是格式错误的,因此它们不能具有相同的类型 - 最好两者都是不正确的。
这很好。不同的数字不仅是不必要的,而且也不会做任何事情 - 别名模板是透明的,因此数字会消失,因为您在实际的类型表达式中没有使用它。
只有当两个EnableIf
条件 时,然后才会在两者中以相同的类型(detail::enabler
)结束功能。
答案 1 :(得分:0)
看起来我在抽奖时速度太快,并将Barry's answer标记为正确答案。然而,它似乎不太正确,或者至少不清楚。
只要参数不同,函数就可以具有有效的重载。模板函数是相同的,但其签名还包括模板参数。因此,您可以使用相同的参数列表具有相同的函数名称,但使用不同的模板参数,它仍将被视为过载。
因此,如果两个函数都具有相同类型T
的可行性,则会发生冲突。
但是,由于EnableIf
仅在互斥条件下解析为某种类型,因此即使第二种模板类型将解析为相同类型detail::enabler
,第一个模板参数也会是一个不同的类型(即使没有基于函数参数的自动推导,具有相同的函数参数类型,这仍然有效)。因此,这仍然是一个不同的函数重载。
@Barry说std::enable_if_t<std::is_same<T, int>::value, detail::enabler>
和std::enable_if_t<std::is_same<T, float>::value, detail::enabler>
是完全不相关的类型。他有点正确。如果有效,他们会确定完全相同的类型,但他没有提到的是他们在同一时间并不是有效的。