模板 class 的友元运算符 <<,带有额外的默认模板参数
friend operator<< of a template class, with additional default template parameter
在下面的代码中,A
是一个模板 class,取决于非类型 bool type
参数。为 A<true>
和 A<false>
定义了朋友 operator<<
。 operator<<
还依赖于另一个 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<<
的模板参数d
一个默认值,比如d=false
这样的语句
std::cout << atrue;
等同于
operator<< <false>(std::cout, atrue);
因为bool d
采用默认值d=false
并且bool type
是从operator<<
的第二个参数推导出来的。
是否有允许这样做的语法?
如果我在友元声明中插入默认参数
template <bool d = false, bool type>
friend std::ostream& operator<<(std::ostream& os, const A<type>& a);
我得到一个编译错误:
main.cpp:14:71: error: default template arguments may not be used in
template friend declarations
如果我在operator<<
的代码中插入默认参数
template <bool d = false, bool type>
std::ostream& operator<<(std::ostream& os, const A<type>& a)
{
...
同样它没有编译给出错误
main.cpp:27:15: error: redeclaration of friend 'template std::ostream& operator<<(std::ostream&, const A&)' may not
have default template arguments
27 | std::ostream& operator<<(std::ostream& os, const A& a)
main.cpp:14:26: note: 'template std::ostream&
operator<<(std::ostream&, const A&)' previously declared here
14 | friend std::ostream& operator<<(std::ostream& os, const
A& a);
好的,其实解决起来还是比较简单的。在 class 专业化之前添加模板 operator<<
的 声明 就足够了:
template <bool type>
class A;
template <bool d = false, bool type>
std::ostream& operator<<(std::ostream& os, const A<type>& a);
....
这样A<type>
里面的friend
声明就不会首先声明operator<<
,而只是声明它是一个friend
。
可以检查一个工作示例 here.
在下面的代码中,A
是一个模板 class,取决于非类型 bool type
参数。为 A<true>
和 A<false>
定义了朋友 operator<<
。 operator<<
还依赖于另一个 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<<
的模板参数d
一个默认值,比如d=false
这样的语句
std::cout << atrue;
等同于
operator<< <false>(std::cout, atrue);
因为bool d
采用默认值d=false
并且bool type
是从operator<<
的第二个参数推导出来的。
是否有允许这样做的语法?
如果我在友元声明中插入默认参数
template <bool d = false, bool type>
friend std::ostream& operator<<(std::ostream& os, const A<type>& a);
我得到一个编译错误:
main.cpp:14:71: error: default template arguments may not be used in template friend declarations
如果我在operator<<
template <bool d = false, bool type>
std::ostream& operator<<(std::ostream& os, const A<type>& a)
{
...
同样它没有编译给出错误
main.cpp:27:15: error: redeclaration of friend 'template std::ostream& operator<<(std::ostream&, const A&)' may not have default template arguments
27 | std::ostream& operator<<(std::ostream& os, const A& a)
main.cpp:14:26: note: 'template std::ostream& operator<<(std::ostream&, const A&)' previously declared here
14 | friend std::ostream& operator<<(std::ostream& os, const A& a);
好的,其实解决起来还是比较简单的。在 class 专业化之前添加模板 operator<<
的 声明 就足够了:
template <bool type>
class A;
template <bool d = false, bool type>
std::ostream& operator<<(std::ostream& os, const A<type>& a);
....
这样A<type>
里面的friend
声明就不会首先声明operator<<
,而只是声明它是一个friend
。
可以检查一个工作示例 here.