gpt4 book ai didi

c++ - 模板化 ostream 重载歧义错误 : basic_ostream vs const char[]

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:46:05 26 4
gpt4 key购买 nike

我正在尝试了解 ostream 重载。考虑一下

#include <iostream>

using std::ostream;

enum class A{a1, a2, a3};

template <class T>
ostream& operator<<(ostream& out, const T& a)
{
switch(a)
{
case T::a1 :
return out<<"a1";
case T::a2 :
return out<<"a2";
case T::a3 :
return out<<"a3";
};
return out;
}
/*ostream& operator<<(ostream& out, const A& a)
{
switch(a)
{
case A::a1 :
return out<<"a1";
case A::a2 :
return out<<"a2";
case A::a3 :
return out<<"a3";
};
return out;
}*/

int main()
{
A a = A::a3;
std::cout<<a<<std::endl;
}

编译时出现如下错误

test.cpp:13:17: error: ambiguous overload for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘const char [3]’)
return out<<"a1";
^

虽然取消注释正常功能和注释模板版本工作正常。为什么二义性不是在正常功能中,为什么是模板化版本

最佳答案

非模板运算符不会引起任何歧义,因为该运算符本身无法解决此调用:

return out << "a1";
// ^^^^^^^^^^^
// This MUST be `std::operator <<`, no other valid overload of
// operator << is found!

以及其他类似的。

另一方面,模板版本是可行的,因为T不一定是任何具体类型:

template <class T>
ostream& operator<<(ostream& out, const T& a)
{
switch(a)
{
case T::a1 :
return out << "a1";
// ^^^^^^^^^^^
// Here the compiler could invoke std::operator <<
// OR it could invoke your operator << template,
// which is also viable since T could be anything!
// Which one should it pick?

// ...
}
}

因此,编译器不知道是否在std 中选择重载。命名空间或您的函数模板(是的,那将是建立无限递归的尝试,但编译器不需要关心)。

这些重载都很好,因此存在歧义。

解决问题的一种方法是对 operator << 的 SFINAE 模板重载进行约束。以便仅当 T 时才考虑重载决议是枚举类型。例如:

#include <type_traits>

template <class T,
typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
ostream& operator<<(ostream& out, const T& a)

这是一个live example .

关于c++ - 模板化 ostream 重载歧义错误 : basic_ostream<char> vs const char[],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17192694/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com