给定以下程序
#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? 这是因为这里考虑了名字,并且在模板推导完成后,我们调用同一函数模板的定义?
我认为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&&) {}