0

同じ構文を使用してすべての型に対してシームレスに機能できるstd::iterator_traits::value_typeに似た構造を作成したいと思います。次のようなものがあると想像してください。

template <typename T>
struct value_type {
  typedef T type;
};

#define VALUE_TYPE(T) typename value_type<T >::type

これはPODタイプで機能します。私はそれを自分のクラスに特化することができます:

struct MyClass {
  typedef float value_type;
};

template <>
struct value_type<MyClass> {
  typedef MyClass::value_type type;
};

ただし、理想的な世界では、余分なvalue_typeのインスタンス化は避けたいと思います。

問題はSTLイテレータにあります。イテレータ階層に到達するための専門分野が必要です。コンパイラが基本ケースを選択するため、これは失敗します。

template <>
struct value_type<std::_Iterator_base_aux> {  // MSVC implementation
  typedef value_type type;
};

階層の上位にあるクラス(value_typeが定義されている場所であるため、_Iterator_with_baseが最も自然です)を選択すると、すべてのイテレーター特性をテンプレート引数として指定する必要があるため、失敗します。

私がやろうとしていることはC++でも可能ですか?

4

2 に答える 2

3

SFINAEを使用して、value_typetypedefの存在を検出できます。個々のタイプに特化する必要はありません(内部実装の詳細に完全に依存しているため、これは不可能な場合があります)。

#include <vector>

template <class T>
struct has_value_type
{
    typedef char true_type;
    typedef char false_type[2];

    //template not available if there's no nested value_type in U's scope
    template <class U>
    static true_type test(typename U::value_type* ); 

    //fallback
    template <class U>
    static false_type& test(...);

    //tests which overload of test is chosen for T
    static const bool value = sizeof(test<T>(0)) == sizeof(true_type);
};

template <class T, bool b>
struct value_type_impl;

template <class T>
struct value_type_impl<T, false> //if T doesn't define value_type
{
    typedef T type;
};

template <class T>
struct value_type_impl<T, true> //if T defines value_type
{
    typedef typename T::value_type type;
};

template <class T>
struct value_type: value_type_impl<T, has_value_type<T>::value>
{
};

struct MyClass {
  typedef float value_type;
};

template <class T>
int foo(T )
{
    return typename value_type<T>::type();
}

int main()
{
    foo(MyClass());
    std::vector<int> vec;
    foo(vec.begin());
    foo(10);
}
于 2010-02-18T20:13:44.473 に答える
1

UncleBensSFINAEを使用しましたが、実際にはもっと簡単です。

template <class T>
struct value_type
{
  typedef typename T::value_type type;
};

さて、あなたがコントロールするクラスでそれを使いたいなら、最も簡単な方法は次のとおりです:

struct MyClass { typedef float value_type; };

BOOST_MPL_ASSERT((boost::is_same< MyClass::value_type,
                                  typename value_type<MyClass>::type >));

また、自分が管理していないクラスに使用したい場合でも、専門分野があります。

struct ThirdPartyClass {};

template <>
struct value_type<ThirdPartyClass> { typedef int type; }

value_type内部がなく、特殊化が利用できないクラスに使用しようとするtypedefと、コンパイルエラーになります(そして、一見理解できないメッセージです...)

于 2010-02-19T09:07:46.643 に答える