c++ - 简化的元组实现

标签 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;
};

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

我正在寻找一个尽可能简单的实现。

最佳答案

您可以使用 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>();
}

这是一个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 .

关于c++ - 简化的元组实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17454225/

相关文章:

c++ - 在结构图上使用 find(),得到 "has no member named XXX"

c++ - 扭曲的二项式系数

c++ - std::function 函数与函数指针

c++ - 在 C++11 中迭代 vector 时从 vector 中删除元素

c++ - std::map 初始化列表构造函数

c++追加到链表

C++ 无锁 C 风格共享数组(用于添加元素)

android - 我如何告诉 Android Studio 将 GCC 4.9 与 CMake 一起使用?

c++ - 调用可访问类成员的成员函数的 Lambda 函数

c++ - Eclipse 显示错误,但项目编译并执行