我正在一个没有任何标准库的平台上工作,而且我正在 尝试实现“类元组”类型。
我只需要按类型获取的工具,但我希望编译器能够
如果类型不存在,则发出 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_if
和 std::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/