35

任意の変数型が反復可能かどうかを確認する方法はありますか?

インデックス付きの要素があるかどうかを確認するには、実際にその子のループをループできますか? (たとえば foreach を使用しますか?)

そのためのユニバーサルテンプレートを作成することは可能ですか?

検索中に他のプログラミング言語のテクニックを見つけました。それでも、C++ でこれを行う方法を見つける必要があります。

4

6 に答える 6

34

そのための特性を作成できます。

namespace detail
{
    // To allow ADL with custom begin/end
    using std::begin;
    using std::end;

    template <typename T>
    auto is_iterable_impl(int)
    -> decltype (
        begin(std::declval<T&>()) != end(std::declval<T&>()), // begin/end and operator !=
        void(), // Handle evil operator ,
        ++std::declval<decltype(begin(std::declval<T&>()))&>(), // operator ++
        void(*begin(std::declval<T&>())), // operator*
        std::true_type{});

    template <typename T>
    std::false_type is_iterable_impl(...);

}

template <typename T>
using is_iterable = decltype(detail::is_iterable_impl<T>(0));

実例

于 2015-04-14T18:35:18.240 に答える
5

「反復可能」の意味によって異なります。イテレータはさまざまな方法で実装できるため、C++ ではあいまいな概念です。

foreachC++11 の範囲ベースの for ループについて言及している場合は、型begin()とメソッドを定義し、 、 、 およびend()に応答する反復子を返す必要があります。operator!=operator++operator*

Boost の BOOST_FOREACH ヘルパーを意味する場合は、BOOST_FOREACH Extensibilityを参照してください。

設計に、反復可能なすべてのコンテナーが継承する共通のインターフェイスがある場合、C++11 のstd::is_base_ofを使用できます。

struct A : IterableInterface {}
struct B {}
template <typename T>
constexpr bool is_iterable() {
    return std::is_base_of<IterableInterface, T>::value;
}
is_iterable<A>(); // true
is_iterable<B>(); // false
于 2012-12-11T23:35:03.800 に答える
1

または、(私のように)すべての SFINAE ソリューションがダミーの構造体定義の大きなブロックであり::type::value無意味であることが嫌いな場合は、すばやく(非常に)汚いワンライナーを使用する例を次に示します。

template <
    class Container,
    typename ValueType = decltype(*std::begin(std::declval<Container>()))>
static void foo(Container& container)
{
    for (ValueType& item : container)
    {
        ...
    }
}

最後のテンプレート引数は、1 つのステップで複数のことを行います。

  1. 型にbegin()メンバー関数または同等のものがあるかどうかを確認します。
  2. 関数begin()が定義済みのものを返すことを確認しますoperator*()(イテレータの場合に典型的)。
  3. イテレータを逆参照した結果の型を決定し、テンプレートの実装で役立つ場合に備えて保存します。

end()制限: 一致するメンバー関数があることを再確認しません。

より堅牢で完全な再利用可能なものが必要な場合は、代わりに他の優れた提案されたソリューションのいずれかを使用してください。

于 2019-08-28T23:57:58.827 に答える