运算符<<的两阶段查找

Kor*_*ose 3 c++ templates

目前我正在尝试为<<我正在处理的类重载插入操作符.出于某种原因,我将其分成两个函数,并从另一个函数中调用一个函数.切换到模板后,它不再起作用了.在查找问题之后,我发现了两个阶段查找和背后的一些推理.

基本上,我试图做的是以下内容:

template <typename Foo, typename Bar>
class MyClass {
public:
  using foo_t = Foo;
  using bar_t = Bar;

  bar_t some_func() const { /* do something */ }
};

/* Level 2 operator */
template <typename Foo, typename Bar>
std::ostream& operator<<(std::ostream& out, const typename MyClass<Foo,Bar>::bar_t& bar) {
  return out << some_other_func(bar);
}

/* Level 1 operator calls level 2 operator */
template <typename Foo, typename Bar>
std::ostream& operator<<(std::ostream& out, const MyClass<Foo,Bar>& myClass) {
  return out << myClass.some_func();
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,由于这bar_t是依赖的事实,这不会编译我将1级操作符更改为以下内容:

template <typename Foo, typename Bar>
std::ostream& operator<<(std::ostream& out, const MyClass<Foo,Bar>& myClass) {
  return operator<<<Foo,Bar>(out,myClass.some_func());
}
Run Code Online (Sandbox Code Playgroud)

现在这可能不是很漂亮,我认为这会消除<<操作员的目的.

除了不拆分两个操作员的明显解决方案之外,有没有人有一个很好的解决方案呢?

Ser*_*eyA 5

您描述的问题与两步查找无关.相反,它与函数中的事实有关

template <typename Foo, typename Bar>
std::ostream& operator<<(std::ostream& out, const typename MyClass<Foo,Bar>::bar_t& bar)
Run Code Online (Sandbox Code Playgroud)

Foo并且Bar处于非推断的上下文中.这意味着,每次调用函数时都必须提供这些模板参数.

至于虽然编译器不能在这里推断出类型,但让我们考虑一个不起作用的同一个更简单的例子:

template<class T> struct A {
    using type = int;
    type i = 42;
};

template<class T> void foo(typename A<T>::type );
...
A<void*> a;
foo(a.i); // problematic call
Run Code Online (Sandbox Code Playgroud)

您可能希望在上面的示例中T推断出void*.但是,type a.i是int.所以这个电话是相同的

foo(int(42));
Run Code Online (Sandbox Code Playgroud)

显然,没有有意义的T编译器可以在这里推断出来.

至于如何解决这个问题 - 尽量不要将非推导类型与流一起使用.如果你不能,那么流插入操作符可能不适合这个,因为语法真的很难看.只需使用普通功能.