5

我有一个定义一些成员类型的模板类。它类似于基于它自己的模板参数std::map定义它的方式,但在我的情况下,类型更复杂,所以它被定义为嵌套类。value_type

现在为了调试,我想operator<<为该类型定义。但是编译器告诉我它不能推导出外部模板的模板参数。

我的真实代码不像下面的例子那样做作,但是这个做作的例子演示了我尝试过的方法以及它是如何失败的:

#include <iostream>

template <typename Value> class Outer;

template <typename Value>
std::ostream &operator<<(std::ostream &, const typename Outer<Value>::Inner &);

template <typename Value>
class Outer {
  public:
    struct Inner {
    Value x;
    };

    void PrintSomething(Value v) {
    // the real program does something useful with the inner class, of course
    Inner inner = { v };
    std::cout << "Inner = " << inner << std::endl; // <---- THIS SAYS IT CAN'T FIND operator<<
    };
};

template <typename Value>
std::ostream &operator<<(std::ostream &s, const typename Outer<Value>::Inner &v) {
    return s << v.x;
}

int main() {
    Outer<int> o;
    o.PrintSomething(42);
    return 0;
}

这是重现问题的完整示例。编译器(我已经尝试了其中的 3 个)说没有重载operator<<需要 type 的第二个参数Outer<int>::Inner。当我用没有其他重载的不同函数尝试相同的事情时,它反而说C2783: could not deduce template argument for 'identifier',gcc 和 clang 一直说没有采用第二个参数的重载Outer<int>::Inner)。

那么有没有一种方法来定义operator<<任何Outer<Value>::Inner正确Value(所以它不能被定义为成员)参数?

注意:我需要它在几个编译器中编译,其中一些没有任何 C++11 功能,所以我需要它是 C++03。

4

1 回答 1

6

你所拥有的是所谓的不可演绎的上下文。怎么可能Value推断出来?您可以部分专门化类模板,使编译器几乎不可能尝试和测试每个可能的实例化(其中有......嗯,无限的)。

有两种解决方法:Inner退出Outer,或结交operator<<内联朋友。后者是人们通常的方式。

template<class T>
struct Outer{
  struct Inner{
    T value;
    friend std::ostream& operator<<(std::ostream& os, Inner const& v){
      return os << v.value:
    }
  };
  // ...
};
于 2013-03-14T14:48:18.490 回答