鉴于以下计划
#include <type_traits>
#include <utility>
template <typename T, typename std::enable_if_t<std::is_same<std::decay_t<T>, int>::value>*>
void foo(T&&);
template <typename T, typename std::enable_if_t<std::is_same<std::decay_t<T>, int>::value>* = nullptr>
void foo(T&&) {}
int main() {
foo(int{});
}
https://wandbox.org/permlink/rlASqofr0Is38lop
Clang很好地编译了这段代码(https://wandbox.org/permlink/xCfDNvTlYD2x7WG3),但是gcc给出了一个错误,说它无法推断出匿名模板参数。谁是对的?
我查看了函数模板部分[temp.fct]
中的标准,发现了类似的内容。有一个关于哪个函数模板是首选的部分,我们有两个相同的函数模板,具有不同的名称查找 - 匿名非类型模板参数是否构成“依赖名称”?这是标准中的相关文字
为了确定两个相关名称(17.6.2)是否相同,只考虑名称本身,而不是模板上下文中的名称查找结果。如果同一函数模板的多个声明在此名称查找的结果中不同,则使用第一个声明的结果。
template <class T> decltype(g(T())) h(); int g(int); template <class T> decltype(g(T())) h() { return g(T()); } int i = h<int>();
鉴于上面示例中的两个相同的函数模板,如果第一个是首选的,那么在我的情况下这同样适用吗?在我的案例中,名称查找在哪里?这是否意味着铿锵有误?
为什么这个程序会编译 - https://wandbox.org/permlink/I0tcHTPvGMWbdpC3?这是因为这里考虑了第一个名字,在完成模板推导后我们调用了相同函数模板的定义吗?
答案 0 :(得分:1)
我认为Clang在这里是正确的。
来自[temp.param / 10]:
可以使用的默认模板参数集合由。获得 合并来自所有先前声明的默认参数 模板的方式与默认函数参数相同(11.3.6)。 [ 实施例:
template<class T1, class T2 = int> class A; template<class T1 = int, class T2> class A;
相当于
template<class T1 = int, class T2 = int> class A;
- 结束示例]
在您的示例中,您有两个模板foo
的声明(请参阅[temp / 1]),因此它们应相当于:
template <typename T, typename std::enable_if_t<std::is_same<std::decay_t<T>, int>::value>* = nullptr>
void foo(T&&) {}