重载模板结构内结构的运算符 [duplicate]

Overload an operator of a struct inside a template struct [duplicate]

提问人:edrezen 提问时间:11/15/2023 最后编辑:Remy Lebeauedrezen 更新时间:11/15/2023 访问量:149

问:

我有一个模板结构,它定义了一个内部结构。FooBar

现在,我想重载这个内部结构的流,但编译器似乎忽略了我的重载实现:operator <<Bar

错误:与“operator<<”不匹配(操作数类型为“std::ostream”{又名“std::basic_ostream<char>”}和“Foo<3>::Bar”)

我的代码如下:

#include <iostream>

//////////////////////////////////////////////////////////////////////////////////////////
template<int N>
struct Foo
{
    struct Bar  {};
};

//////////////////////////////////////////////////////////////////////////////////////////
template<int N>
std::ostream& operator<< (std::ostream& os, const typename Foo<N>::Bar& x)
{
    return os;
}

//////////////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
    Foo<3>::Bar x;

    std::cout << x << std::endl;
}

我看不到(也许很明显的)错误。

问题是否可以重载属于模板类的内部结构的运算符?

C++ 结构 运算符重载

评论

0赞 user12002570 11/15/2023
模板化类的嵌套类中的 Dupe:friend 运算符

答:

2赞 Pepijn Kramer 11/15/2023 #1

你是这个意思吗? 使用模板类,通常更容易在模板中声明友元重载(此处的演示:https://onlinegdb.com/NqTLD6_tU)

#include <iostream>

template<int N>
struct Foo
{
    struct Bar
    { 
        int x{N};
    };
    
    // friend if you need access to a private member
    friend std::ostream& operator<<(std::ostream& os, const Foo<N>::Bar& bar)
    {
        os << bar.x;
        return os;
    }

private:
    Bar b; 
};

int main (int argc, char** argv)
{
    Foo<3>::Bar x;
    std::cout << x << "\n";
}

评论

0赞 Jerry Coffin 11/15/2023
请注意,由于它现在位于 的定义中,因此您可以稍微简化运算符的参数声明,将其简化为 ,而不是 。godbolt.org/z/33xno8qMbFooconst Bar &const Foo<N>::Bar &
0赞 edrezen 11/15/2023
谢谢你的回答。我很确定我尝试了类似的东西,但还不够相似,无法编译!
5赞 463035818_is_not_an_ai 11/15/2023 #2

是的,像这样:

#include <iostream>

template<int N>
struct Foo
{
    struct Bar  {
        friend std::ostream& operator<<(std::ostream& os,const Bar&) { return os;}
    };
};

int main (int argc, char** argv)
{
    Foo<3>::Bar x;

    std::cout << x << std::endl;
}

在您的代码中,实际上并没有错。它只是不可能从中推断出来。您只能通过显式调用它:operator<<NFoo<N>::BarN

int main (int argc, char** argv)
{
    Foo<3>::Bar x;
    operator<<<3>(std::cout,x);
}

现场演示


原因是这是一个不可推导的上下文。有关更多详细信息,请参阅什么是非推导上下文?简而言之,这不起作用的原因是 和 之间没有 1:1 的关系。考虑添加专业化:Foo<N>::BarFoo<N>::BarN

template <> struct Foo<42> {
      using Bar = Foo<3>::Bar;
};

现在并引用完全相同的类型。这Foo<42>::BarFoo<3>::Bar

Foo<3>::Bar x;
std::cout << x;

和这个

Foo<42>::Bar x;
std::cout << x;

必须推断出不同的值,但在两个示例中都是完全相同的类型。Nx

评论

0赞 edrezen 11/15/2023
感谢您的详细回答;我今天在 C++ 中学到了一些新东西,我想我面前有很多这样的日子!