为嵌套类模板重载运算符<<

5

我有以下设置:

template< class T >
struct Foo {

  struct Bar {
    Bar ( const T &t ) : otherT_( t ) {}

    T otherT_;
  };

  Foo ( const T &t ) : myT_( t ) {}

  T myT_;
};

现在,我想使 Foo< T >::Bar 的实例能够输出到 std::cout 和其他相关函数。我尝试了以下方法:

template< class T >
std::ostream& operator<< ( std::ostream &os, 
                           const typename Foo< T >::Bar &bar ) {
  os << "<bar: " << bar.otherT_ << ">";
  return os;
}

但是以下代码无法编译:
  Foo< int > foo( 5 );
  Foo< int >::Bar bar( 7 );

  std::cout << bar << std::endl;

我猜测编译器无法推断类型 T 或其他原因导致了问题。有没有办法使嵌套类的这种情况与 operator<< 良好地配合?

谢谢!


1
复制/粘贴此答案:http://stackoverflow.com/a/18823636/596781? - Kerrek SB
1
@KerrekSB 我不确定是否理解所引用的答案。他出错的原因很简单:Foo<T>::Bar中的 T 是无法推导的上下文,详见 §14.8.2.5/5。正如其他人所指出的那样,将该函数设置为友元是可行的(因为生成的函数不是一个模板,所以不需要进行类型推导)。 - James Kanze
@JamesKanze:「未推导的上下文」是这两个问题的共同原因。问题通常出现在认为可以通过解决 Foo<T>::Bar = X 中的 T 来得到 X 的想法上。 - Kerrek SB
@KerrekSB 这不是你能否解决某个问题的问题,而是标准规定你不允许尝试。 (实际上,这个问题是可以解决的,但是标准委员会认为它对当前编译器技术来说过于复杂。) - James Kanze
@JamesKanze:好的,在这种非常严格的情况下,可以。但是考虑一下 template <> struct Foo<int> { typedef int Bar; };。突然间你破坏了 std::cout << 10;... - Kerrek SB
显示剩余4条评论
3个回答

10

没错,简单的方法是将 operator<< 放在 Bar 内部:

struct Bar {
  Bar ( const T &t ) : otherT_( t ) {}

  T otherT_;

  friend std::ostream& operator<< ( std::ostream &os, const Bar &bar ) 
  {
    os << "<bar: " << bar.otherT_ << ">";
    return os;
  }
};

我正在朝相反的方向挖掘...

仍在尝试另一种方法 :) - Raffi
我曾认为模板别名可能有助于推断,但是这个答案让我清醒了。链接 - TemplateRex

3

解决方法 - 在Bar的定义中将operator<<定义为友元函数:

template< class T >
struct Foo {

  struct Bar {
    Bar ( const T &t ) : otherT_( t ) {}

    T otherT_;

    friend std::ostream& operator<< ( std::ostream &os, const Bar &bar )
    {
      os << "<bar: " << bar.otherT_ << ">";
      return os;
    }

  };

  Foo ( const T &t ) : myT_( t ) {}

  T myT_;
};

你的方法存在问题,正如KerrekSB在评论中所说,T无法被推断。对于Foo::Bar,可能有无限多个T,每个T可能会导致不同的类型。

1
编译器无法推断T,但是当你将其设为友元时,它会通过ADL找到它。
我已将代码修改为以下内容:
#include <iostream>
using namespace std;

template< class T >
struct Foo {

struct Bar {
Bar ( const T &t ) : otherT_( t ) {}

T otherT_;
friend std::ostream& operator << (std::ostream& os, const Bar &bar )
{ return os; }
};

Foo ( const T &t ) : myT_( t ) {}


T myT_;
};

int main() {
Foo< int > foo( 5 );
Foo< int >::Bar bar( 7 );

std::cout << bar << std::endl;
return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接