[英]Reuse an operator<< for several classes
我有兩個類(這是一個,從我實際更復雜的案例中摘錄)
class ClUInt {
public:
ClUInt() : _i(2), _arr{1,2,3} {};
ClUInt(const unsigned int ui) : _i(ui) {};
private:
unsigned int _i;
double _arr[3];
};
class ClInt {
public:
ClInt() : _i(-2), _arr{-1,-2,-3} {};
ClInt(const int i) : ClInt() { _i = i; };
private:
int _i;
double _arr[3];
};
它們非常相似,但一個使用int
,另一個使用unsigned int
作為成員_i
。
我想重載operator<<
,例如,
std::ostream& operator<<(std::ostream& os, const ClInt & ci)
{
cout << ci._i << endl;
cout << ci._arr[0] << endl;
return os;
}
假設我想要兩個類的“相同”重載。
怎么只寫一次,方便維護? 我想定義我自己的演員表,但我不確定這是要走的路......
筆記:
我想我沒有機會讓這兩個類共享繼承樹的任何部分。
它們實際上可能是struct
,因此如果隱私影響答案,則可以假設_i
和_arr
是public
。
在實際情況下,這兩個struct
分別具有更多數量的有符號/無符號的“公共”成員。
使用帶有概念的模板:
#include <concepts>
#include <iostream>
template<typename T>
concept ClInteger = std::same_as<T, ClInt> || std::same_as<T, ClUInt>;
template <ClInteger T>
std::ostream& operator<<(std::ostream& os, const T & ci)
{
std::cout << ci._i << '\n';
std::cout << ci._arr[0] << '\n';
return os;
}
請注意,此運算符必須是這些類的朋友才能訪問其私有字段。
居住
您可以嘗試使用 SFINAE 創建一個僅適用於這兩種類型的模板化operator<<
。 例如:
template <class T,
std::enable_if_t<
std::is_same<ClInt, std::decay_t<T>>::value
or std::is_same<ClUInt, std::decay_t<T>>::value
, int> = 0>
std::ostream & operator<< (std::ostream & out, T const & obj) {
out << obj._i << '\n';
out << obj._arr[0] << '\n';
return out;
}
上面的示例適用於 C++14,但如果您將std::decay_t<T>
替換為typename std::decay<T>::type
,則可以使其與 C++11 一起使用。
注意:我用'\\n'
替換了std::endl
,因為您可能不想每次都刷新輸出流。 請參閱C++: "std::endl" 與 "\\n" 。
也許這只是巧合,但您的兩個班級共享很多。 那么,為什么不把它們變成模板:
template<typename integer_type>
class IntegerClass
{
/// ... further code elided
friend ostream& operator<<(ostream& out, IntegerClass const& obj)
{
return out
<< obj._i << endl
<< obj._arr[0] << endl;
}
integer_type _i;
double _arr[3];
};
// optional typedefs
// These are a matter of taste, not actually mine.
typedef IntegerClass<unsigned int> ClUInt;
typedef IntegerClass<signed int> ClInt;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.