2010-02-18 61 views
0

我想创建一个类似于std :: iterator_traits :: value_type的构造,它可以使用相同的语法无缝工作于所有类型。想象一下,我们有以下几种:C++的value_type是否可以从iterator_traits扩展到所有类型?

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

手头有什么问题?顺便说一句,你的'value_type'结构通常被称为'identity'。 – GManNickG 2010-02-18 20:14:21

+0

我有不同像素类型的图像,其中一些是结构体,其中一些是浮点数,其中一些是整数。要做一些与它们数学的事情(例如找到平均值)需要告诉编译器用于计算的类型。而且我已经定义了VALUE_TYPE来返回iterator_traits :: value_type,所以最好将它们组合成一个构造。 – 2010-02-19 17:14:56

回答

2

您可以使用SFINAE来检测typedef的存在性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); 
} 
+0

我不得不为T *和const T *添加特化,但我认为它工作正常。谢谢。 – 2010-02-23 01:04:07

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和对于没有专门提供的一类,它是一个编译错误(和消息,你可能不会第一眼就明白...)

+0

但由于float :: value_type不存在,它将无法编译为POD类型的关键情况。 – 2010-02-19 17:11:52

+0

就像'std :: iterator_traits'专门用于指针一样,您需要针对每种无法修改的类型专门化您的结构,是的。 – 2010-02-20 12:49:52

相关问题