我有一个定义某些成员类型的模板类。它与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<<
的重载会采用类型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。
答案 0 :(得分: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:
}
};
// ...
};