我正在开发一个没有任何标准库的平台,而且我是 试图实现“类似元组”类型。
我只需要设备来获取类型,但我希望编译器能够
如果类型不存在,则发出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;
};
我知道它失败的原因,但我不知道如何避免这种限制。
我正在寻找一种尽可能简单的实现方法。
答案 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_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。