3

container_traitsコンテナがそうであるかどうかをチェックするクラスを作成しますstd::array。ただし、から継承されたコンテナをキャッチできませんstd::array。解決策はありますか?

#include <vector>
#include <array>
#include <iostream>

using namespace std;

template<typename C>
struct container_traits { constexpr static bool is_array = false; };
template<typename T, size_t S>
struct container_traits<std::array<T,S>> { constexpr static bool is_array = true; };

template<typename T, size_t S>
struct A : public std::array<T,S> {};

int main()
{
    cout << container_traits<A<int, 5>>::is_array << endl;              // must return 1
    cout << container_traits<std::array<int, 10>>::is_array << endl;    // must return 1
    cout << container_traits<std::vector<int>>::is_array << endl;       // must return 0
    return 0;
}
4

2 に答える 2

7

あなたが使用することができますstd::is_base_of

template <typename C>
struct container_traits {
  constexpr static bool is_array = false;
};

template <template <typename, std::size_t> class C,
          typename T, std::size_t N>
struct container_traits<C<T,N>> {
  constexpr static bool is_array = std::is_base_of<std::array<T,N>, C<T,N>>::value;
};

実際の動作をご覧ください

これは基本的に、2つのパラメーターを受け取るテンプレートタイプに特化しています。そして、その専門分野では、の値is_arrayはによって決定されstd::is_base_ofます。

于 2013-03-25T14:05:48.467 に答える
6

著者のメモ:このソリューションに投票しないでください。代わりにsftrabbitに投票してください。私のものよりも優れているからです。欠陥はあるものの、アイデアが面白いと感じた人もいたので、削除はしません。

これにより、必要な結果が得られます。

template<typename C>
struct container_traits {

private:

   template <typename T, size_t N>
   static char (&is_array_helper(const std::array<T, N>&))[1];

   static char (&is_array_helper(...))[2];

public:

    constexpr static bool is_array =
        sizeof(is_array_helper(std::declval<C>())) == sizeof(char[1]);

};

std::array<T, N>(例えば)から派生するクラスの場合A、継承はpublicそうでなければコードがコンパイルされないことを言及する価値があります。これを修正するには、std::is_base_ofSFINAE手法を使用または適用できます。ただし、アクセシビリティに関するSFINAEルールはC++03からC++11に変更されており、しばらく前にテストしたところ、一部の主要なコンパイラは新しいルールを実装していませんでした。彼らは今そうするかもしれません。

質問の作成者に、より良い解決策が見つかるかどうかを確認することをお勧めします(これが実現することを願っています)。

于 2013-03-25T14:11:10.877 に答える