使用非类型模板参数正向声明函数模板



给定以下程序

#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&&) {}

最新更新