2014-02-10 37 views
0

在這個例子中工作:模板部分特不與的typedef

template<typename T> 
struct ConditionalValue 
{ 
    typedef boost::optional<T> type; 
}; 

template<typename T> 
struct FindRootValueType 
{ 
    typedef typename T::root_type type; 
}; 

template<typename T> 
struct FindRootValueType<typename ConditionalValue<T>::type> 
{ 
    typedef typename ConditionalValue<T>::type type; 
}; 

template<typename T> 
struct Base 
{ 
    typedef T value_type; 
    typedef typename FindRootValueType<value_type>::type root_type; 
    std::vector<value_type> data; 
}; 

template<typename T> 
struct A : public Base<typename ConditionalValue<T>::type> 
{ 
}; 

template<typename T> 
struct B : public Base<A<T>> 
{ 
}; 

template<typename T> 
struct C : public Base<B<T>> 
{ 
}; 

// C<int>::value_type == B<int> 
// C<int>::data == std::vector<B<int>> 
// C<int>::data ~= std::vector<std::vector<std::vector<boost::optional<int>>>> 
// C<int>::root_type == boost::optional<int> 

ConditionalValue是模板別名,僅僅試圖給出的替代名稱到boost::optional(使得別的可用來代替它),並FindRootValueType是一個元函數,用於逐步定義類似於底部顯示的類型的鏈,直到它停在boost::optional處,然後簡單地返回該鏈。

然而,正如所寫,這不起作用(至少不在VS2008)。爲了解決這個問題,FindRootValueType的專門化必須明確地使用boost::optional<T>,而不是應該與其等效的typedef。 (並且這違背了只在一個地方指定底層實現類型的目標)。

這是編譯器錯誤還是這應該不起作用?或者我只是做錯了什麼?有沒有更好的方式來編寫它,使其按預期工作?

我也試過正是如此顛倒的邏輯:

template<typename T> 
struct FindRootValueType 
{ 
    typedef T type; 
}; 

// define Base here 

template<typename T> 
struct FindRootValueType<Base<T>> 
{ 
    typedef typename T::root_type type; 
}; 

// define A here 

template<typename T> 
struct FindRootValueType<A<T>> 
{ 
    typedef T type; 
}; 

// define B, C here (no specialisation) 

但是,這並不工作,要麼(我想是因爲專業化不遵循基本類型,或者可能是定義的只是順序)。我不想專門針對B,C等。

(順便說一句,在上述兩個的,「不工作」的意思是編譯器錯誤被產生的表示,它用的FindRootValueType基本定義,而不是專門化。)

回答

0

靈感來自this answer到相關問題的鏈接,我試過以下,它似乎工作:

template<typename T> 
struct HasRootType 
{ 
private: 
    typedef char no; 
    struct yes { no m[2]; }; 

    static T* make(); 
    template<typename U> 
    static yes check(U*, typename U::root_type* = 0); 
    static no check(...); 

public: 
    static bool const value = sizeof(check(make())) == sizeof(yes); 
}; 

template<typename T, bool = HasRootType<T>::value> 
struct FindRootValueType 
{ 
    typedef typename T::root_type type; 
}; 

template<typename T> 
struct FindRootValueType<T, false> 
{ 
    typedef T type; 
}; 

// define Base, A, B, C, etc here 

因此重新定義的問題「走了類型,直到找到一個沒有root_type,然後返回」。不過,我仍然很好奇爲什麼基於typedef的專業化似乎不起作用。