【问题标题】:friend operator<< of a template class, with additional default template parameter模板类的友元运算符<<,带有附加的默认模板参数
【发布时间】:2020-02-03 13:49:11
【问题描述】:

在下面的代码中,A 是一个模板类,取决于一个非类型的bool type 参数。为A&lt;true&gt;A&lt;false&gt; 定义了一个朋友operator&lt;&lt;operator&lt;&lt; 还依赖于另一个 bool 模板参数。

#include <ostream>
#include <iostream>
#include <type_traits>

template <bool type>
class A;

template <>
class A<true> {
    int m_x;
public:
    A(int x) : m_x{x} { }
    template <bool d, bool type>
    friend std::ostream& operator<<(std::ostream& os, const A<type>& a);
};

template <>
class A<false> {
    int m_y;
public:
    A(int y) : m_y{y} { }
    template <bool d, bool type>
    friend std::ostream& operator<<(std::ostream& os, const A<type>& a);
};

template <bool d, bool type>
std::ostream& operator<<(std::ostream& os, const A<type>& a)
{
    if constexpr (type) {
        os << "m_x = " << a.m_x << std::endl;
        if constexpr (d) { os << "2m_x = " << a.m_x << std::endl; }
    }
    else {
        os << "m_y = " << a.m_y << std::endl;
        if constexpr (d) { os << "2m_y = " << a.m_y << std::endl; }
    }
    return os;
}


int main()
{
    A<true> atrue{2};
    A<false> afalse{3};

    operator<< <true>(std::cout, atrue);
    operator<< <false>(std::cout, atrue);

    operator<< <true>(std::cout, afalse);
    operator<< <false>(std::cout, afalse);

    return 0;
}

live on Coliru

现在,我想给operator&lt;&lt; 的模板参数d 的默认值,比如d=false 这样的语句

std::cout << atrue;

等价于

operator<< <false>(std::cout, atrue);

因为bool d 采用默认值d=falsebool type 是从operator&lt;&lt; 的第二个参数推导出来的。

有允许这样做的语法吗?

如果我在朋友声明中插入默认参数

template <bool d = false, bool type>
friend std::ostream& operator<<(std::ostream& os, const A<type>& a);

我得到一个编译错误:

main.cpp:14:71: 错误:默认模板参数不能用于 模板友元声明

如果我在operator&lt;&lt;的代码中插入默认参数

template <bool d = false, bool type>
std::ostream& operator<<(std::ostream& os, const A<type>& a)
{
...

再次编译时出现错误

main.cpp:27:15: 错误:朋友'template std::ostream& operator

27 | std::ostream& 运算符

main.cpp:14:26: 注意:'模板 std::ostream& operator

14 |朋友 std::ostream& 运算符

【问题讨论】:

  • 不如使用operator &lt;&lt; 以外的名称作为print,因为您不能“正常”使用它?

标签: c++ templates operator-overloading friend


【解决方案1】:

好的,实际上解决方案相对容易。在类专业化之前添加模板operator&lt;&lt;声明就足够了:

template <bool type>
class A;

template <bool d = false, bool type>
std::ostream& operator<<(std::ostream& os, const A<type>& a);
....

这样A&lt;type&gt; 中的friend 声明首先不会声明operator&lt;&lt;,而只是声明它是friend。 可以查看工作示例here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    • 2020-01-28
    • 2011-05-08
    • 2020-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多