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

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

我正在尝试做的事情甚至可能在 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

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

于 2010-02-19T09:07:46.643 回答