2015-09-16 8 views
7

を見つけ、私はそうC++のコンテナがある場合::()

私は

std::set<std::string> a, c; 
... 
asserter<std::string, std::set> ass(c); 
for_each(a.begin(), a.end(), ass); 
として使用する場合があります
template<typename T, template<typename...> class U> 
class asserter 
{ 
public: 
    asserter(U<T> &c) : container(c) { }; 
    void operator()(T lhs) 
    { 
     CU_ASSERT(container.find(lhs) != container.end()); 
    }; 
private: 
    U<T> &container; 
}; 

のようなタイプTの要素の型Uのコンテナで動作数子を持っているかを決定

ここでは、現在std::includes()を無視しています。

これは、コンテナがU::find()が定義されているコンテナの場合に効果的です。それがなければ、std::find()にフォールバックしたいと思います。一方、std::find()が利用可能であれば、むしろU::find()を使用したいと思います。 C++ 11(又は17必要に応じて)で

私はU::find()はUのために(おそらくSTLに制限)が利用可能であるかどうかを決定し、それを使用する場合、別段std::find()を使用できますか?

答えて

7

SFINAEの式c.find(value)が整形式であるかどうか。末尾の戻り値の型はC++ 11です。とにかくここでは必須ではありません。戻り値の型を簡単に書くことができます - decltype(std::declval<Container&>().find(std::declval<const T&>()))の代わりにdecltype(c.find(value))

式が正しく形成されない場合、最初のオーバーロードはfind_implで、オーバーロードセットから削除され、2番目のオーバーロードは唯一の実行可能なものとして残ります。第3のパラメータの通常のint/long/0トリックは、両方が実行可能である場合に第1の過負荷を優先させます。

template<class Container, class T> 
auto find_impl(Container& c, const T& value, int) -> decltype(c.find(value)){ 
    return c.find(value); 
} 

template<class Container, class T> 
auto find_impl(Container& c, const T& value, long) -> decltype(std::begin(c)){ 
    return std::find(std::begin(c), std::end(c), value); 
} 

template<class Container, class T> 
auto find(Container& c, const T& value) -> decltype(find_impl(c, value, 0)) { 
    return find_impl(c, value, 0); 
} 

通常の免責条項が適用されます。これは、現在、MSVCでサポートされていない表現SFINAE、に依存しています。マイクロソフトでは、MSVC 2015のアップデートでサポートを追加する予定です。

+4

さらに便利な答えは、コードが動作する理由を説明します。たとえば、私はSFINAEを採用した答えを期待していました。 'decltype(...)'部分はC++ 17のSFINAEテクニックです(このラムダ式の構文はC++ 17だと思います)。また、 'int'は' long'オーバーロードよりもその署名を優先させるために使われますか? –

+0

'std :: set :: find'などが等価であるのに対して、' std :: find'は等価であるという心配があります。それを考慮する必要がありますか? –

+0

@ニッキーC理論的にはそれらは異なっているが、現実世界ではそれはどれくらいの頻度であるのだろうか?私は 'set'と' map'(そしてそれらの 'multi'のいとこ)が重要なのは唯一のものだと思います。' unordered_set'と 'unordered_map'は等価を使うべきです。 –

関連する問題