非推导上下文中模板参数推导的解决方法

发布于 2024-12-18 13:04:33 字数 970 浏览 4 评论 0原文

考虑以下代码:

#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 external::inner 是一个非推导上下文(如此处),这意味着编译器无法推导模板参数类型(请阅读这个答案了解原因)。在我看来,我有两个选择来使其工作:

  1. inner 移到 outer 之外,并将其设为类模板。我更喜欢这个,因为对使用代码的影响更小。
  2. 向内部添加一个 to_string 方法。

是否有其他解决方案(不会导致使用代码中出现丑陋的语法)?

Consider the following code:

#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
}

This does not compile, because typename outer<T>::inner is a nondeduced context (as explained here), meaning the template-argument-type cannot be deduced by the compiler (read this answer for the why). As I see it, I have two options to make it work:

  1. Move inner outside of outer and make it a class-template. I prefer this one, because the impact on the using code is smaller.
  2. Add a to_string-method to inner.

Are there any other solutions for this (that do not result in ugly syntax in the using code)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

万劫不复 2024-12-25 13:04:33

您可以将运算符移动到内部类主体中,并将​​ friend 放在它前面。然后将参数类型替换为 inner

另一种技术是从由内部参数化的 CRTP 基础派生内部。然后使参数类型为 CRTP 类,并将参数引用强制转换为派生的 inner 类,该类的类型由您推导的模板参数给出。

You can move the operator into the inner class body and put friend before it. Then replace the parameter type by just inner.

Another technique is to derive inner from a CRTP base parameterized by inner. Then make the parameter type the CRTP class and cast the parameter reference to the derived inner class, the type of which is given by the template argument you deduce.

青朷 2024-12-25 13:04:33

正如我所想,这是非推导上下文的嵌套名称说明符情况,请参阅cppreference
但这并不意味着您不能显式指定 operator<< 的模板类型。
有用:

#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
    operator<<<float>(std::cout, foo);  
}

As I suppose, it is the nested-name-specifier case of the non deduced context, see cppreference.
But it does not mean that you can't specify template types for operator<< explicitly.
It works:

#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
    operator<<<float>(std::cout, foo);  
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文