C ++的value_type可以从iterator_traits扩展到所有类型吗?

时间:2010-02-18 19:48:21

标签: c++ templates iterator generic-programming

我想创建一个类似于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;
};

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

我正在尝试用C ++做什么?

2 个答案:

答案 0 :(得分:3)

您可以使用SFINAE检测是否存在value_type typedef。无需专门针对个别类型(这可能是不可能的,因为您完全依赖于内部实现细节)。

#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);
}

答案 1 :(得分:1)

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且没有可用专业化的类,则会出现编译错误(以及您不太可能理解的消息)乍一看......)