代码之家  ›  专栏  ›  技术社区  ›  Mark Ruzon

C++的值类型能从迭代器扩展到所有类型吗?

  •  0
  • Mark Ruzon  · 技术社区  · 16 年前

    template <typename T>
    struct value_type {
      typedef T type;
    };
    
    #define VALUE_TYPE(T) typename value_type<T >::type
    

    这将适用于吊舱类型。我可以专门为我自己的班级做:

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

    尽管在理想情况下,我更希望避免额外的值类型实例化。

    问题在于STL迭代器。我需要一个专门化,让我到迭代器层次结构。此操作失败,因为编译器选择基本情况:

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

    选择层次结构中更高的类(带基的迭代器是最自然的,因为这是定义值类型的地方)失败,因为它需要将所有迭代器特性指定为模板参数。

    2 回复  |  直到 16 年前
        1
  •  3
  •   UncleBens    16 年前

    您可以使用SFINAE检测 value_type

    #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);
    }
    
        2
  •  1
  •   Matthieu M.    16 年前

    UncleBens 使用了SFINAE,但实际上更简单:

    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 对于没有专门化的代码,这是一个编译错误(以及一条您乍一看不太可能理解的消息…)