1
當編寫一個模板函數,如:通用算法調用每個元素打印集合中
template<class T> void print(T const & collection)
當通過收集循環和提領該迭代一切工作的權利,如果你,除非你改變它有類似vector<int>
到vector<int*>
。處理單個模板函數中的差異而不重複代碼的最佳方式是什麼?
當編寫一個模板函數,如:通用算法調用每個元素打印集合中
template<class T> void print(T const & collection)
當通過收集循環和提領該迭代一切工作的權利,如果你,除非你改變它有類似vector<int>
到vector<int*>
。處理單個模板函數中的差異而不重複代碼的最佳方式是什麼?
我會寫一個模板函數do_print
委託給類模板printer
。類模板是一個函數對象,做了漂亮的印刷,這部分你只需調用*t
漂亮的印刷版專門爲T*
。
因此,有沒有漂亮的打印代碼的重複和寫兩個輕量級的實現類一小麻煩(這是用來取得任何現代編譯器優化掉,所以沒有運行時開銷)。
我喜歡這個解決方案在SFINAE技巧,因爲部分類專門爲您提供了比函數重載花樣更多的控制(和更好的錯誤消息)。它也推薦由Sutter編碼標準Alexandrescu &。
順便說一句,此代碼也將爲T**
工作,因爲T*
的專門代表T
的代碼。所以T**
發送到T*
,最後發送到T
。實際上,任意級別的間接方向可以簡化爲打印由指針指向的元素。
#include <iostream>
#include <vector>
namespace detail {
template<typename T>
struct printer
{
void operator()(T const& t)
{
std::cout << t; // your pretty print code here
}
};
template<typename T>
struct printer<T*>
{
void operator()(T const* t)
{
printer<T>()(*t); // delegate to printing elements (no duplication of prettty print)
}
};
}
template<typename T>
void do_print(T const& t)
{
detail::printer<T>()(t);
}
template<typename C>
void print(C const& collection)
{
for(auto&& c: collection)
do_print(c);
std::cout << "\n";
}
int main()
{
int a = 1;
int b = 2;
auto c = &a;
auto d = &b;
std::vector<int> v1 { a, b };
std::vector<int*> v2 { c, d };
std::vector<int**> v3 { &c, &d };
print(v1);
print(v2);
print(v3);
}
所以,你需要同時支持值類型和引用類型的輸出?你在做什麼'print()'方法?如果你只是將它們傳遞給你,那麼你只需要一個實現。如果您需要訪問成員,則需要SFINAE在編譯時在值或引用類型的實現之間切換。 –
爲指針類型提供一個模板函數,只需解除引用並傳遞給引用類型函數?這似乎很簡單,我錯過了什麼? – Chad
你需要訪問集合的底層'value_type'(幸好,最暴露它),不管它是什麼。然後,如佈雷特所描述的,SFINAE一套人爲設計的專業化可能是一條好路徑。老實說,你可能會寫一個'print()',它會使用迭代器並專注於'iterator_traits <>'類信息。 – WhozCraig