对于嵌套在类模板中的类X,operator <<(ostream&,X)

n. *_* m. 15 c++ templates

这个编译和工作应该(非嵌套模板):

#include <iostream>

template<typename T> class Z;

template <typename T> 
std::ostream& operator<< (std::ostream& os, const Z<T>&) {
    return (os << "Z");
}

template<typename T> class Z {
    friend std::ostream& operator<< <> (std::ostream& os, const Z&);
};

int main () {
    Z<int> z;
    std::cout << z << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这个不编译(gcc 4.4和gcc 4.6,在03和0x模式下):

#include <iostream>

template<typename T> class Z;

template<typename T> 
std::ostream& operator<< (std::ostream& os, const typename Z<T>::ZZ&) {
    return (os << "ZZ!");
}

template <typename T> class Z {
  public:
    class ZZ {
        friend std::ostream& operator<< <> (std::ostream& os, const ZZ&);
    };
};


int main () {
    Z<int>::ZZ zz;
    std::cout << zz << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

错误消息如下所示:

error: template-id ‘operator<< <>’ for ‘std::ostream& operator<<(std::ostream&,
const Z<int>::ZZ&)’ does not match any template declaration
error: no match for ‘operator<<’ in ‘std::cout << zz’
Run Code Online (Sandbox Code Playgroud)

在0x模式下,第二条错误消息不同,但含义相同.

有可能做我想做的事吗?

编辑显然,这里有一个非推断上下文的实例,它解释了错误消息.然而,问题仍然存在:我可以operator<<为嵌套在类模板中的类工作吗?

Mat*_* M. 7

这是功能的一般问题:

template <typename C>
void func(typename C::iterator i);
Run Code Online (Sandbox Code Playgroud)

现在,如果我打电话func(int*),C我应该使用哪个值?

一般来说,你不能倒退!许多不同的人C可能已经定义了一个内部类型iterator,恰好是int*某些参数集.

在你的情况下,你有点复杂的情况:

template <typename T>
void func(typename Z<T>::ZZ const&);
Run Code Online (Sandbox Code Playgroud)

但从根本上说这是同一个问题,Z<T>是一个模板,而不是一个完整的类,你要求为ZZ这个模板的内部类型创建一个函数.

假设我这样做:

template <typename T>
struct Z { typedef T ZZ; };

template <typename T>
struct Z<T const> { typedef T ZZ; };
Run Code Online (Sandbox Code Playgroud)

注意:典型的迭代器,value_type不是const限定的

然后,在调用时func(int),我应该使用Z<int>Z<int const>

这是不可扣除的.

因此,整个事物被称为不可推导的背景,标准禁止它,因为没有明智的答案.

经验法则:typename对函数的参数持怀疑态度.

注意:如果另一个参数已经固定了类型,它们就可以了,例如typename C::iterator find(C&, typename C::const_reference);因为一旦C推断出来,那么C::const_reference可以毫无困难地使用它们


Shi*_*oko 3

马蒂厄很好地解释了这个问题,但在这种情况下可以使用一个简单的解决方法。您可以使用友元声明在类中实现友元函数:

#include <iostream>

template <typename T> class Z {
public:
  class ZZ {
    friend std::ostream& operator<< (std::ostream& os, const ZZ&) {
      return os << "ZZ!";
    }
  };
};


int main () {
  Z<int>::ZZ zz;
  std::cout << zz << std::endl;
}
Run Code Online (Sandbox Code Playgroud)