有一個container模板化的容器類,所以它可以包含任何東西。
我想添加列印其內容的能力,std::ostream所以我已經覆寫了operator<<.
然而,這有一個缺點:如果容器包含參考(或指標),該方法只列印地址而不是真實資訊。
請考慮這個演示問題的簡單測驗代碼:
#include <iostream>
#include <deque>
template<typename T, bool is_reference = false>
class container {
public:
container() {}
void add(T a) { queue.push_back(a); }
friend std::ostream& operator<<(std::ostream& out, const container<T, is_reference>& c) {
for (const T& item : c.queue) {
if (is_reference) out << *item; else out << item;
out << ",";
}
return out;
}
private:
std::deque<T> queue;
};
int main() {
//Containers
container<int*, true> myContainer1;
container<int> myContainer2;
int myA1(1);
int myA2(10);
myContainer1.add(&myA1);
myContainer1.add(&myA2);
myContainer2.add(myA1);
myContainer2.add(myA2);
std::cout << myA1 << std::endl;
std::cout << myA2 << std::endl;
std::cout << myContainer1 << std::endl;
std::cout << myContainer2 << std::endl;
return 0;
}
我想在模板中提供一個額外的is_reference布林值來調整operator<<.
但是,如果我有值型別容器,這會導致早期編譯器錯誤。
我怎樣才能使這項作業?
如果我將列印機線更改為
out << item << ",";
代碼編譯并列印:
1
10
0x7ffd77357a90,0x7ffd77357a94,
1,10,
顯然我的目標是得到這個結果:
1
10
1,10,
1,10,
(如何)我可以輕松實作這一目標嗎?
uj5u.com熱心網友回復:
您可以使用 SFINAE 根據std::is_pointer<T>::value是true還是來選擇多載false。這已經適用于 C 11:
#include <iostream>
#include <deque>
template<typename T>
class container {
public:
// container() {} // dont define empty constructor when not needed
// or declare it as = default
void add(const T& a) { queue.push_back(a); } // should take const&
template <typename U = T, typename std::enable_if< std::is_pointer<U>::value,bool>::type=true>
friend std::ostream& operator<<(std::ostream& out, const container<T>& c) {
std::cout << "is pointer\n";
}
template <typename U = T, typename std::enable_if< ! std::is_pointer<U>::value,bool>::type=true>
friend std::ostream& operator<<(std::ostream& out, const container<T>& c) {
std::cout << "is not pointer\n";
}
private:
std::deque<T> queue;
};
int main() {
//Containers
container<int*> myContainer1;
container<int> myContainer2;
std::cout << myContainer1 << std::endl;
std::cout << myContainer2 << std::endl;
}
輸出:
is pointer
is not pointer
從 C 17 開始,您可以使用constexpr if. 此外,由于存在 C 17,std::is_pointer_v并且由于存在 C 14 std::enable_if_t,兩者都會使代碼不那么冗長。
uj5u.com熱心網友回復:
對于item和*item作業之間的條件選擇,您將需要一個支持 C 17 標準(或更高版本)的編譯器,然后使用if constexpr (...)陳述句。
此外,您可以使用std::is_pointer檢查包含的型別是否為指標,而不是在模板中添加“標志”:
#include <iostream>
#include <deque>
#include <type_traits>
template<typename T>
class container {
public:
container() {}
void add(T a) { queue.push_back(a); }
friend std::ostream& operator<<(std::ostream& out, const container<T>& c) {
for (const T& item : c.queue) {
if constexpr (std::is_pointer<T>::value) {
out << *item;
}
else {
out << item;
}
out << ",";
}
return out;
}
private:
std::deque<T> queue;
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/467033.html
