简化的元组实现

时间:2013-07-03 17:12:03

标签: c++ c++11

我正在开发一个没有任何标准库的平台,而且我是 试图实现“类似元组”类型。

我只需要设备来获取类型,但我希望编译器能够 如果类型不存在,则发出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;
};

我知道它失败的原因,但我不知道如何避免这种限制。

我正在寻找一种尽可能简单的实现方法。

1 个答案:

答案 0 :(得分:7)

根据类型T是否与Head相同,您可以使用SFINAE使两个重载中只有一个参与重载决策:

#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>();
}

以下live example使用上述static_assert()

如果您还想测试一个元组是否只包含某个类型,您可以使用以下特征,这是对上面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