12

現在、テンプレートのメタプログラミングを行っています。私の場合、「反復可能な」型、つまり atypedef foo const_iteratorが同じ方法で存在する型を処理できます。これに新しい C++11 テンプレート メタプログラミングを使用しようとしましたが、特定の型が欠落しているかどうかを検出する方法が見つかりませんでした。

他の特性に基づいて他のテンプレートの特殊化もオン/オフにする必要があるため、現在 2 つのパラメーターを持つテンプレートを使用しており、2 つ目のパラメーターはstd::enable_if. これが私が現在行っていることです:

template <typename T, typename Enable = void>
struct Foo{}; // default case is invalid

template <typename T>
struct Foo< T, typename std::enable_if<std::is_fundamental<T>::value>::type>{ 
   void do_stuff(){ ... }
};

template<typename T>
struct exists{
   static const bool value = true;
};

template<typename T>
struct Foo<T, typename std::enable_if<exists< typename T::const_iterator >::value >::type> {
    void do_stuff(){ ... }
};

existsヘルパー テンプレートがないと、このようなことはできませんでした。たとえば、単純に

template<typename T>
struct Foo<T, typename T::const_iterator> {
    void do_stuff(){ ... }
};

この特殊化を使用する必要がある場合に、無効なデフォルトのケースが代わりにインスタンス化されたため、機能しませんでした。

ただしexists、新しい C++11 標準のどこにもこれを見つけることができませんでしboost::type_traitsた。ただし、ホームページboost::type_traitsは、代わりに使用できるものへの参照は表示されません。

この機能が欠けているのでしょうか、それとも、目的の動作を達成するための他の明白な方法を見落としていましたか?

4

4 に答える 4

15

特定のタイプにが含まれている場合const_iteratorは、コードの簡略化されたバージョンを以下に示します。

template<typename T>
struct void_ { typedef void type; };

template<typename T, typename = void>
struct Foo {};

template<typename T>
struct Foo <T, typename void_<typename T::const_iterator>::type> {
      void do_stuff(){ ... }
};

この手法がどのように機能するかの説明については、この回答を参照してください。

于 2011-10-20T11:12:29.243 に答える
7

has_const_iteratorブール値を提供する特性を作成し、それを特殊化で使用できます。

このような何かがそれを行うかもしれません:

template <typename T>
struct has_const_iterator {
private:
    template <typename T1>
    static typename T1::const_iterator test(int);
    template <typename>
    static void test(...);
public:
    enum { value = !std::is_void<decltype(test<T>(0))>::value };
};

そして、次のように特化できます。

template <typename T,
          bool IsFundamental = std::is_fundamental<T>::value,
          bool HasConstIterator = has_const_iterator<T>::value>
struct Foo; // default case is invalid, so no definition!

template <typename T>
struct Foo< T, true, false>{ 
   void do_stuff(){// bla }
};

template<typename T>
struct Foo<T, false, true> {
    void do_stuff(){//bla}
};
于 2011-10-20T10:35:26.103 に答える
4

メンバータイプの特性チェックの別のバージョンは次のとおりです。

template<typename T>
struct has_const_iterator
{
private:
    typedef char                      yes;
    typedef struct { char array[2]; } no;

    template<typename C> static yes test(typename C::const_iterator*);
    template<typename C> static no  test(...);
public:
    static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
于 2011-10-20T10:59:31.843 に答える
2

これを行うにはいくつかの方法があります。C++03 では、boost を使用enable_ifしてトレイト ( docssource )を定義できます。

BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator);

template <typename T, typename Enable = void>
struct Foo;

template <typename T>
struct Foo< T, typename boost::enable_if<boost::is_fundamental<T> >::type>{ 
   void do_stuff(){ ... }
};

template<typename T>
struct Foo<T, typename boost::enable_if<has_const_iterator<T> >::type> {
    void do_stuff(){ ... }
};

C++11 では、次のようにTickを使用できます。

TICK_TRAIT(has_const_iterator)
{
    template<class T>
    auto require(const T&) -> valid<
        has_type<typename T::const_iterator>
    >;
};

template <typename T, typename Enable = void>
struct Foo;

template <typename T>
struct Foo< T, TICK_CLASS_REQUIRES(std::is_fundamental<T>::value)>{ 
   void do_stuff(){ ... }
};

template<typename T>
struct Foo<T, TICK_CLASS_REQUIRES(has_const_iterator<T>())> {
    void do_stuff(){ ... }
};

また、Tickを使用すると、トレイトをさらに拡張して、const_iteratorが実際にイテレータであることを実際に検出することもできます。is_iteratorしたがって、次のような単純なトレイトを定義するとします。

TICK_TRAIT(is_iterator,
    std::is_copy_constructible<_>)
{
    template<class I>
    auto require(I&& i) -> valid<
        decltype(*i),
        decltype(++i)
    >;
};

次に、次のように型が特性と一致has_const_iteratorすることを確認する特性を定義できます。const_iteratoris_iterator

TICK_TRAIT(has_const_iterator)
{
    template<class T>
    auto require(const T&) -> valid<
        has_type<typename T::const_iterator, is_iterator<_>>
    >;
};
于 2014-07-01T23:11:04.687 に答える