2013-07-16 77 views
1

確保模板參數是容器的機制是什麼?有沒有辦法確保模板參數是一個容器?

另外,我怎麼可以根據它的參數是否是容器或不是爲類/函數做不同的專業化?

+1

任何容器或標準庫容器? – Borgleader

+2

爲什麼?整個觀點是你不應該在意。只要正確的功能可用,讓實例化工作。否則,你就會走上一條黑暗而危險的道路:「只有我才能選擇哪種類型是'正確的'」 –

+0

你稱之爲集裝箱?容器是否擁有其內容? – Yakk

回答

1

完整吹塑容器的測試很困難且不明確。就個人而言,我認爲容器當且僅當它擁有它的直接內容,但這可能不符合其他人對該術語的使用。

迭代性的測試既不困難也不含糊,通常是在函數參數中採用對象時要測試的內容。有些迭代的東西不是非常容易的(例如C++ 1y或C++ 1z的string_view)。

我認爲,在C++ 11,一個實例下的X型的是當且僅當可迭代:

for(auto&& a : c) {} 

是公形成。爲上述選擇的措辭意味着您可以使用beginend自由函數重載擴展任何類型以使其成爲可迭代的。

一個體面的逼近,如果將上面的工作將是檢驗如果在參數依賴啓用查找背景下,std::beginstd::end回報的東西,有一個有效的std::iterator_traits<>

作爲一個速寫,我得到的是這樣的:

template<typename T, typename=void> 
struct is_iterable : std::false_type {}; 

namespace aux { 
    using std::begin; 
    // note: no implementation 
    template<typename C> 
    auto adl_begin(C&& c)->decltype(begin(std::forward<C>(c))); 
    using std::end; 
    // note: no implementation 
    template<typename C> 
    auto adl_end(C&& c)->decltype(end(std::forward<C>(c))); 
} 
template<typename T> 
struct is_iterable<T, 
    typename std::enable_if< 
    std::is_same< 
     typename std::iterator_traits< typename std::decay<decltype(aux::adl_begin(std::declval<T>()))>::type >::iterator_category, 
     typename std::iterator_traits< typename std::decay<decltype(aux::adl_end(std::declval<T>()))>::type >::iterator_category 
    >::value 
    >::type 
> : std::true_type {}; 

Live example

容器,同時,很少是因爲統一。他們最基本的「常見」過程,如添加元素,在簽名和語義方面各不相同。 erase(iterator)::allocator_type是容器狀結構的兩個最常見的特徵,但std::array<T,N>T[N]可以說是容器並且沒有屬性。

簡而言之,超越它們的可迭代性的共同屬性,容器差別太大了,因爲那裏有非常有用的特性類。相反,你應該計算出你正在尋找的容器的屬性(刪除元素的能力,插入元素的能力,隨機訪問),然後測試它們。

+0

我應該在之前指定過ti,但是有沒有類似於您爲舊版C++所做的工作? – Srv19

+0

@ Srv19只有勉強。你打算如何獲得沒有'std :: begin'和'std :: end'的可迭代對象的迭代器?你可以推出你自己的虛擬'std :: begin'和'std :: end',其行爲相似。我使用'std :: enable_if'和'std :: declval'和'std :: decay'的其他C++ 11特性同樣很容易重新實現,並且可能具有'boost'等效。 – Yakk

+0

你的解釋是合理和有用的,併爲我的進一步研究提供了方向。似乎我必須接受它) – Srv19

1

的另一種方法是使用boost::spirit::traits::is_container<>

mpl::true_返回如果T具有以下嵌入類型定義:value_typeiteratorsize_type,和reference。否則,它將返回mpl::false_

適用於C++ 03及以上版本。

相關問題