我想爲所有具有基於範圍基礎的類實現漂亮打印,以支持超載< <。 (錯誤)代碼是這樣的。漂亮的打印所有具有基於範圍基礎的類支持循環支持
template<class C> ostream& operator<<(ostream& out, const C& v) {
for(auto x : v) out<<x<<' ';
return out;
}
的這裏的問題是,這將與現有的< <重載衝突。有沒有一種方法可以在模板中指定C必須支持ranged-for循環?
我想爲所有具有基於範圍基礎的類實現漂亮打印,以支持超載< <。 (錯誤)代碼是這樣的。漂亮的打印所有具有基於範圍基礎的類支持循環支持
template<class C> ostream& operator<<(ostream& out, const C& v) {
for(auto x : v) out<<x<<' ';
return out;
}
的這裏的問題是,這將與現有的< <重載衝突。有沒有一種方法可以在模板中指定C必須支持ranged-for循環?
由於基於範圍的for循環需要begin(v)
和end(v)
要與ADL(和std::
是相關的命名空間)有效,您可以使用此:
namespace support_begin_end
{
// we use a special namespace (above) to
// contain the using directive for 'std':
using namespace std;
// the second parameter is only valid
// when begin(C()) and end(C()) are valid
template<typename C,
typename=decltype(begin(std::declval<C>()),end(std::declval<C>()))
>
struct impl
{
using type = void; // only here impl
};
// explicitly disable conflicting types here
template<>
struct impl<std::string>;
}
// this uses the above to check for ::type,
// which only exists if begin/end are valid
// and there is no specialization to disable it
// (like in the std::string case)
template<class C,typename = typename supports_begin_end::impl<C>::type>
std::ostream& operator<<(std::ostream& out, const C& v) {
for(auto x : v) out<<x<<' ';
return out;
}
還有其他類型的雖然,它適用於基於範圍的循環。不知道你是否也需要檢測它們。
這裏有一個更新的live example檢測兩個容器/支持begin(v)
/end(v)
以及支持v.begin()
/v.end()
種類型。
SFINAE:
template<class C>
auto operator<<(std::ostream& out, const C& v) -> decltype(v.begin(), v.end(), (out))
// or -> decltype(std::begin(v), std::end(v), (out))
{
for (auto x : v)
out << x << ' ';
return out;
}
A於所有的答案一般性評論:
使用
for (auto x : v)
將複製出來的集合中的所有元素打印前,造成了很多對拷貝構造函數和析構函數的調用。你可能更好用
for (auto &x : v)
作爲你的循環。
你介意解釋一下這裏發生的一些事情嗎?會是可愛的謝謝! – lfxgroove
@lfxgroove看看更新的答案是否有幫助。 –
當然可以,謝謝你! – lfxgroove