2013-07-03 73 views
4

我正在研究一個不支持任何標準庫的平臺,我試圖實現一個「元組類型」類型的 。簡化的元組實現

我只需要設備按類型,但我希望編譯器 發出static_assert如果類型不存在。有沒有必要在複製類型斷言 ,但它會很美好......

這是我曾嘗試:

template<class... Args> struct SimpleTuple; 

template<> struct SimpleTuple<> { 
    SimpleTuple() { } 
}; 

template<class Head, class... Tail> 
struct SimpleTuple<Head, Tail...> { 
    typedef Head HeadType; 
    typedef SimpleTuple<Tail...> VATailType; 

    SimpleTuple(Head head, Tail... tail) : data(head), rest(tail...) { } 

    // Does not compile, because explicit specialization in non-namespace 
    // scope is not allowed 
    template<typename T> T& get() { 
     return rest.get<T>(); 
    } 

    template<> Head& get() { 
     return data; 
    } 

    Head data; 
    VATailType rest; 
}; 

我知道爲什麼會失敗,但我不知道該怎麼避免這種限制。

我正在尋找儘可能簡單的實現。

回答

7

你可以使用SFINAE只讓兩個重載之一,參與過載的分辨率,基於該類型T是否是一樣的Head

#include <type_traits> // For std::enable_if and std::is_same 

template<typename T, 
    typename std::enable_if<!std::is_same<T, Head>::value>::type* = nullptr> 
T& get() { 
    return rest.get<T>(); 
} 

template<typename T, 
    typename std::enable_if<std::is_same<T, Head>::value>::type* = nullptr> 
Head& get() { 
    return data; 
} 

兩個std::enable_ifstd::is_same可以輕鬆實現如果你不能使用標準庫中的那些。例如:

template<typename T, typename U> 
struct is_same { static constexpr bool value = false; }; 

template<typename T> 
struct is_same<T, T> { static constexpr bool value = true; }; 

template<bool C, typename T = void> 
struct enable_if { }; 

template<typename T> 
struct enable_if<true, T> { using type = T; }; 

這裏是一個live example

對於靜態斷言的問題,可以定義一個簡單的特徵來檢查給定的類型是否存在於給定的元組類型中(這個特徵也可以根據std::conditional定義,這也是微不足道的) :

template<typename...> struct SimpleTuple; 

template<typename T, typename U> 
struct has_type { static constexpr bool value = false; }; 

template<typename T, typename U, typename... Ts> 
struct has_type<T, SimpleTuple<U, Ts...>> 
{ 
    static constexpr bool value = has_type<T, SimpleTuple<Ts...>>::value; 
}; 

template<typename T, typename... Ts> 
struct has_type<T, SimpleTuple<T, Ts...>> 
{ 
    static constexpr bool value = true; 
}; 

template<typename T> 
struct has_type<T, SimpleTuple<>> 
{ 
    static constexpr bool value = false; 
}; 

,然後用它像這樣:

template<typename T, 
    typename enable_if<!is_same<T, Head>::value>::type* = nullptr> 
T& get() { 
    static_assert(has_type<T, SimpleTuple>::value, "Type not found!"); 
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  
    return rest.get<T>(); 
} 

下面是一個使用上述static_assert()一個live example

如果你也想測試一個元組是否包含某種類型只有一次,你可以使用下面的特質,這是has_type特質上面的一個微不足道的修改:

template<typename...> struct SimpleTuple; 

template<typename T, typename U> 
struct has_unique_type { static constexpr bool value = false; }; 

template<typename T, typename U, typename... Ts> 
struct has_unique_type<T, SimpleTuple<U, Ts...>> 
{ 
    static constexpr bool value = has_unique_type<T, SimpleTuple<Ts...>>::value; 
}; 

template<typename T, typename... Ts> 
struct has_unique_type<T, SimpleTuple<T, Ts...>> 
{ 
    static constexpr bool value = 
     !has_unique_type<T, SimpleTuple<Ts...>>::value; 
}; 

template<typename T> 
struct has_unique_type<T, SimpleTuple<>> 
{ 
    static constexpr bool value = false; 
}; 

並使用它像這樣:

template<typename T, 
    typename enable_if<!is_same<T, Head>::value>::type* = nullptr> 
T& get() { 
    static_assert(has_unique_type<T, SimpleTuple>::value, 
     "Type not found or not unique!"); 

    return rest.get<T>(); 
} 

這是live example