模板化 ostream 重载歧义错误:basic_ostream<char>与常量字符[] [英] Templatized ostream overload ambiguity error : basic_ostream&lt;char&gt; vs const char[]

查看:45
本文介绍了模板化 ostream 重载歧义错误:basic_ostream<char>与常量字符[]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试理解 ostream 重载.考虑这个

I am trying to understand ostream overloads. Consider this

#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";
                 ^

虽然取消注释正常功能和注释模板版本工作正常.为什么歧义不在正常功能中,为什么它在模板化版本中

While uncommenting normal function and commenting template version works fine. Why ambiguity is not in normal function and why it is in templatized version

推荐答案

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

The non-template operator does not cause any ambiguity because that operator itself is not viable for resolving this call:

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

以及其他类似的.

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

The template version, on the other hand, is viable, since T is not bound to be any concrete type:

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 命名空间中的重载还是您的函数模板(是的,这将是尝试建立无限递归,但编译器不会需要关心).

Therefore, the compiler does not know whether to pick the overload in the std namespace or your function template (yes, that would be an attempt to establish an infinite recursion, but the compiler doesn't need to care).

那些重载都很好,因此存在歧义.

Those overloads are both good, hence the ambiguity.

解决问题的一种方法是 SFINAE 约束 operator << 的模板重载,以便仅在 T 时才考虑重载解析枚举类型.例如:

One way to fix your problem would be to SFINAE-constraint your template overload of operator << so that it is considered for overload resolution only when T is an enumeration type. For instance:

#include <type_traits>

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

这是一个示例.

Here is a live example.

这篇关于模板化 ostream 重载歧义错误:basic_ostream<char>与常量字符[]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆