2010-02-18 79 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

相關問題