为什么 c++ 编译器在对两种不同类型的数值变量使用"std::max()"函数时会出现错误
Why c++ compiler gives error when using `std::max()` function for two different type of numeric variable
在函数中使用两种不同的数值变量类型时,c++ 编译器有什么原因std::max()
给出错误吗?(例如int
和long
)。
我的意思是:">有时我们在对两种不同的数值变量类型使用函数时会遇到这个问题std::max()
所以编译器会给出错误以防止这个问题"。
编译器产生错误,因为它无法对std::max
的模板参数执行类型推断。这就是std::max
模板的声明方式:两个参数使用相同的类型(模板参数)。如果参数具有不同的类型,则推论变得模棱两可。
如果您通过显式提供模板参数来解决演绎歧义,您将能够使用不同的类型作为std::max
参数
std::max(1, 2.0); // Error
std::max<double>(1, 2.0); // OK
std::max
坚持为其参数使用公共类型(而不是使用两个独立类型)的原因在@bolov的答案中进行了描述:该函数实际上希望返回对最大值的引用。
std::max
返回对具有最大值的参数的引用。采用这种方式的主要原因是因为它是一个泛型函数,因此它可以与复制成本高昂的类型一起使用。此外,您可能实际上只需要对对象的引用,而不是它的副本。
由于它返回对参数的引用,因此所有参数必须属于同一类型。
这个问题的直接答案是,这是因为std::min
和std::max
只接受一个定义两个参数类型的模板参数。如果/当您尝试传递不同类型的参数时,编译器无法决定将这两种类型中的哪一种用于模板参数,因此代码不明确。根据C++98中的最初定义,std::min
和std::max
具有以下签名(C++03,§[lib.alg.min.max]):
template<class T> const T& min(const T& a, const T& b);
template<class T, class Compare>
const T& min(const T& a, const T& b, Compare comp);
template<class T> const T& max(const T& a, const T& b);
template<class T, class Compare>
const T& max(const T& a, const T& b, Compare comp);
因此,这里的基本思想是函数通过引用接收两个对象,并返回对其中一个对象的引用。如果它收到两种不同类型的对象,它将无法返回对输入对象的引用,因为其中一个对象必然与它返回的类型不同(所以@bolov关于这部分是正确的,但我认为这不是真正的故事)。
使用现代编译器/标准库,如果您不处理值而不是引用,则可以轻松地按照以下一般顺序编写代码:
template <class T, class U>
std::common_type<T, U> min(T const &a, U const &b) {
return b < a ? b : a;
}
template <class T, class U>
std::common_type<T, U> max(T const &a, U const &b) {
return a < b ? b : a;
}
这使得处理传递int
和long
(或其他类型对,只要std::common_type
可以为它们推断出一些通用类型,并且为这两种类型的对象定义a<b
的情况变得非常容易。
但是,在 1998 年,即使std::common_type
可用,所以很容易做到,这个解决方案可能不会被接受(正如我们将看到的,它仍然存在一些问题,它是否是一个好主意)——当时,许多人仍然认为大量的继承,所以(或多或少)被认为是理所当然的,你会经常在两个参数都确实派生的情况下使用它。键入,此一般顺序上的内容:
class Base {
// ...
virtual bool operator<(Base const &other);
};
class Derived1 : public Base {
// ...
};
class Derived2 : public Base {
// ...
};
Derived1 d1;
Derived2 d2;
Base &b = std::max(d1, d2);
在这种情况下,上面返回值而不是返回引用的版本会导致严重的问题。common_type<Derived1, Derived2>
将是Base
的,所以我们最终会切片参数以创建一个类型为Base
的对象,并返回它。这很少会提供理想的行为(在某些情况下,例如,如果Base
是一个抽象基类,它甚至不会编译)。
还有一点可能值得注意:即使在看似简单的情况下应用,std::common_type
也可以产生您可能意想不到的结果。例如,让我们考虑调用上面定义的模板,如下所示:
auto x = min(-1, 1u);
这给我们留下了一个明显的问题:x
会是什么类型?
即使我们已经传递了一个int
和一个unsigned
,结果的类型(至少可能)既不是int
也不是unsigned
(例如,很可能是long long
)!
- <streamsize>C++ 中 numeric_limits::max() 的值
- 黑客级别的Mini-Max Sum
- 'max'匹配'std::function<const int &(const int &, const int &)>'无过载
- 关于 std::min, std::max 中的比较运算符的混淆
- 找到一种有效的方法,在 2 个巨大的缓冲区上执行 MAX,每字节字节
- std::max() 函数与定点实现的比较中的问题
- 使用 CImg 库的 std::min 和 std::max 的编译问题
- 在 3ds Max 中更新进度条后,环境和效果 UI 不刷新
- 从自定义类获取对象向量中的 max 元素
- 如何在C++中递归地找到max元素的索引?
- SFINAE 与 numeric_limits<T>::max() 在 MSVC2017 上
- 这句话是什么意思 - " vector<long long> distance(n, std::numeric_limits<long long>::max()); "?
- 在f2c.h文件中定义min()max()宏时出错
- c++curl返回413请求实体过大,但是post大小远小于max大小
- 在枚举类型上使用std::max是不是一种糟糕的做法
- 为什么Visual Studio 2019不支持用于减少Openmp的关键字"max"?
- 没有函数模板的实例"max"与参数列表参数类型匹配(int、int)
- 'char (*RtlpNumberOf(T (&)[N]))[N]':无法从"char *"
- Arduino IDE 错误 - 无法找到数字文字运算符"运算符""f900ff"
- 如何在 C++11 中将 std::max 与自定义比较器一起使用?