三个参数函数模板令人困惑的示例
Three argument function template confusing example
#include <iostream>
// maximum of two values of any type:
template<typename T>
T max (T a, T b)
{
std::cout << "max<T>() n";
return b < a ? a : b;
}
// maximum of three values of any type:
template<typename T>
T max (T a, T b, T c)
{
return max (max(a,b), c); // uses the template version even for ints
} //because the following declaration comes
// too late:
// maximum of two int values:
int max (int a, int b)
{
std::cout << "max(int,int) n";
return b < a ? a : b;
}
int main()
{
::max(47,11,33); // OOPS: uses max<T>() instead of max(int,int)
}
在这个例子中(来自下面提到的书(,我不明白为什么 ::max(47,11,33( 调用期望使用 max(int,int(。所以一个是 2 个参数,另一个是 3 个参数,我认为它应该使用 3 个参数函数定义。
我错过了什么吗?
注:David Vandevoorde, Nicolai M. Josuttis, Douglas Gregor C++ Templates: The Complete Guide [2nd ed.] book
提出的问题是不会调用非模板重载。
max<T>(T a, T b, T c)
知道max<T>(T a, T b)
但不知道存在整数重载,因为它是在它之后声明的。
解决方案是:专门针对T = int
max<T>
,而不是定义int(int, int)
函数:
#include <iostream>
template<typename T>
T max (T a, T b)
{
std::cout << "max<T>() n";
return b < a ? a : b;
}
template<>
int max (int a, int b)
{
std::cout << "max(int,int) n";
return b < a ? a : b;
}
template<typename T>
T max (T a, T b, T c)
{
return max (max(a,b), c);
}
int main()
{
::max(47,11,33); // BINGO: uses specialized max<int>()
}
输出:
max(int,int)
max(int,int)
不过,如果非模板函数在定义max<T>
之后和max<int>
专用化之前使用max<int>
,这很脆弱,根据[temp.expl.spec]/6
程序格式不正确,无需诊断。
如果这是您无法承担的风险,则可以使用一些工具。SFINAE就是其中之一,可以禁止一般max<T>
与T = int
一起称呼。这将导致工作程序或编译错误。
::max(47, 11, 33);
实际上是::max<int>(47, 11, 33);
反过来会打电话给::max<int>(::max<int>(47, 11), 33);
这可能令人惊讶。
由于int
是内置的(因此没有 ADL(,因此在定义max(T, T, T)
以允许在模板中调用该版本之前,max(int, int)
应该是可见的:
使用自定义类型,借助 ADL,可以在以下之后声明max
函数:
template <typename T>
T max (T a, T b)
{
std::cout << "max<T>()n";
return b < a ? a : b;
}
// Should be declared **before** max(T, T, T)
int max(int a, int b)
{
std::cout << "max(int,int) n";
return b < a ? a : b;
}
template<typename T>
T max (T a, T b, T c)
{
return max (max(a,b), c);
}
struct S {};
// Might be declared after max(T, T, T)
S max(S, S)
{
std::cout << "max(S, S)n";
return {};
}
现在,max(0, 1, 2)
和max(s, s, s)
都将在内部调用非模板重载。
演示
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 嵌套模板函数采用 2 个具有相同内部类型的容器
- 两个函数模板候选项.将一个参数作为引用后,选择不太专业的模板
- 为什么 getch 在按下函数或箭头键时返回三个值?
- 我的动态链接队列在同一输出流中调用时不正确地输出三个返回函数
- 使用模板可变参数函数将多个参数传递给另一个函数
- 如何通过通用引用或std::forward将这三个c++模板函数合并为一个
- 三个参数函数模板令人困惑的示例
- 如何在具有 2 个模板值的类中仅对函数使用 1 个模板值
- 在第三个 pary 函数中使用矢量引用时出现意外错误
- C++ 成员函数的多个定义,基于枚举模板参数
- 在允许的函数模板的明确专业化中扣除了多个模板参数
- 返回函数模板的类型C++作为第二个模板参数
- 访问三个不同的变量在C++中形成三个不同函数中的一个文件
- Java opencv inRange 阈值函数将我的图像分成三个不同的图像
- 如何使用三个参数化构造函数的rand()函数初始化对象的数组
- 将函数两个向量合并为第三个向量
- C++错误,隐 <function-style-cast> 式要求使用模板化类一次调用多个构造函数的多个转换
- 接受子引用作为参数的父函数(或三个相互依赖类的冒险)
- 从一个函数返回三个值