在不可推导的上下文中模板参数推导的解决方法

17

考虑以下代码:

#include <iostream>

template<class T>
struct outer {
    struct inner {};
};

template<class T>
std::ostream& operator<<(std::ostream & stream, 
                         typename outer<T>::inner const& value) {
    std::cout << "An outer::inner!";
    return stream;
}

int main() {
    outer<float>::inner foo;

    std::cout << foo << std::endl; // does not compile
}

这段代码无法编译,因为 typename outer<T>::inner 是一个无法推导的上下文(在这里有解释),这意味着编译器无法推断模板参数类型(请阅读这个答案了解详细原因)。我认为,有两种方法可以使其工作:

  1. inner移出outer并将其变成类模板。我更喜欢这个方案,因为对使用代码的影响较小。
  2. 向内部添加to_string方法。

是否还有其他解决方案可避免使用代码中出现丑陋的语法?

1个回答

23
你可以将操作符移入内部类,然后在其前面加上"friend"。接着将参数类型替换为"inner"即可。
另一种技术是通过CRTP基类从内部派生出"inner"。然后将参数类型设置为CRTP类,并将参数引用转换为派生的"inner"类。你根据推断的模板参数给定的派生"inner"类的类型。

1
“friend”方法很好用。我之前不知道可以在“friend”声明中定义函数(对于那些感兴趣的人:我刚查了一下,它在2003标准的§11.4.5中定义)。 - Björn Pollex

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