c++ - 使用非类型模板参数转发声明函数模板

标签 c++ function templates c++17 sfinae

给定以下程序

#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] 中的标准,发现了类似的东西。当我们有两个具有不同名称查找的相同函数模板时,有一个关于哪个函数模板是首选的部分 - 匿名非类型模板参数是否构成“从属名称”?这是标准中的相关文本

For determining whether two dependent names (17.6.2) are equivalent, only the name itself is considered, not the result of name lookup in the context of the template. If multiple declarations of the same function template differ in the result of this name lookup, the result for the first declaration is used.

template <class T> decltype(g(T())) h();
int g(int);
template <class T> decltype(g(T())) h()
  { return g(T()); }
int i = h<int>();

鉴于上面示例中的两个相同的函数模板,如果第一个是首选,那么这里是否同样适用于我的情况?在我的案例中,名称查找发生在哪里?这是否意味着 clang 是错误的?

为什么这个程序编译 - https://wandbox.org/permlink/I0tcHTPvGMWbdpC3 ?这是因为这里考虑了名字并且在完成模板推导之后我们调用了相同功能模板的定义吗?

最佳答案

我认为 Clang 在这里是正确的。

来自 [temp.param/10]:

The set of default template-arguments available for use is obtained by merging the default arguments from all prior declarations of the template in the same way default function arguments are (11.3.6). [ Example:

template<class T1, class T2 = int> class A;
template<class T1 = int, class T2> class A;

is equivalent to

template<class T1 = int, class T2 = int> class A;

end example ]

在您的示例中,您有两个模板声明 foo(请参阅 [temp/1]),因此它们应该等同于:

template <typename T, typename std::enable_if_t<std::is_same<std::decay_t<T>, int>::value>* = nullptr>
void foo(T&&) {}

关于c++ - 使用非类型模板参数转发声明函数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49397712/

相关文章:

c++ - 可以像普通相机一样使用 pixy

c++ - C++ 中的运算符重载 "<<"

c++ - 二叉树 - 根据级别打印元素

javascript - 如何在另一个函数内的变量内调用函数?

c++ - 在不违反 DRY 原则的情况下对传递的函数对象的参数类型进行模板选择

c++ - 具有函数和模拟部分模板特化的 SFINAE

c++ - 实现比较运算符的模板类

java - 最大和连续子数组(面试题)

c++ - 在函数中使用数组

r - 如何在 R 中的函数中逆向工作