提问人:paulinho 提问时间:10/7/2023 最后编辑:paulinho 更新时间:10/7/2023 访问量:105
取决于类模板参数的条件变量类型
Conditional variant type depending on class template arguments
问:
我有一个类模板,本质上想为将向 API 用户公开的变体类型创建一个模板别名:
template <bool InsertsAllowed, DeletesAllowed>
class Executor {
...
public:
// Ideally, would be
// std::variant<ReadRequest, {InsertRequest only if InsertsAllowed}, {DeleteRequest only if DeletesAllowed}>
// e.g. InsertsAllowed = true, DeletesAllowed = False ==> std::variant<ReadRequest, InsertRequest>
// InsertsAllowed = true, DeletesAllowed = True ==> std::variant<ReadRequest, InsertRequest, DeleteRequest>
using RequestType = ...
makeRequest(const RequestType &r);
...
}
到目前为止,我能想到的最好的解决方案是
template <bool InsertsAllowed, DeletesAllowed>
class Executor {
...
public:
struct BAD_TYPE = {};
using RequestType = std::variant<
ReadRequest,
std::conditional<InsertsAllowed, InsertRequest, BAD_TYPE>,
std::conditional<DeleletesAllowed, DeleteRequest, BAD_TYPE>>;
makeRequest(const RequestType &r);
...
}
但这并不能完全实现我的目标,无论如何都不是最干净的解决方案。
我需要能够引用 ,所以不幸的是我不能用 替换。此外,我想避免堆叠一堆条件来实现我的目标,以防我需要添加更多模板参数以达到类似的效果。RequestType
BAD_TYPE
void
答:
1赞
Eugene
10/7/2023
#1
首先,您需要创建一个元函数,以有条件地将另一种类型附加到 的模板参数列表中。让我们命名它:std::variant
condit_append
#include <type_traits>
#include <variant>
template<bool cond, typename A, typename B>
struct condit_append;
template<bool cond, typename U, typename ...T>
struct condit_append<cond, std::variant<T...>, U>
{
using type = std::conditional_t<cond,
std::variant<T..., U>,
std::variant<T...>
>;
};
接下来,让我们为它创建一个方便别名,类似于标准特征的操作方式:
template<bool cond, typename ...T>
using condit_append_t = typename condit_append<cond, T...>::type;
最后,将其用于您的课程:
class ReadRequest;
class InsertRequest;
class DeleteRequest;
template <bool InsertsAllowed, bool DeletesAllowed>
class Executor {
using Type1 = std::variant<ReadRequest>;
using Type2 = condit_append_t<InsertsAllowed,Type1, InsertRequest>;
public:
using RequestType = condit_append_t<DeletesAllowed,Type2, DeleteRequest>;
//...
};
1赞
Jarod42
10/7/2023
#2
std::tuple
已经具有函数 std::tuple_cat
。
因此,您可能有:
using RequestTypeTuple = decltype(std::tuple_cat(
std::declval<std::tuple<ReadRequest>>(),
std::declval<std::conditional_t<InsertsAllowed,
std::tuple<InsertRequest>, std::tuple<>>>(),
std::declval<std::conditional_t<DeleletesAllowed,
std::tuple<DeleteRequest>, std::tuple<>>>()
));
然后是一个简单的“映射”特征,将元组转换为变体:
template <typename> struct to_variant_impl;
template <typename... Ts> struct to_variant_impl<std::tuple<Ts...>>
{
using type = std::variant<Ts...>;
};
template <typename T>
using to_variant_t = typename to_variant_impl<T>::type;
所以你的班级将是:
template <bool InsertsAllowed, DeletesAllowed>
class Executor {
using RequestTypeTuple = decltype(std::tuple_cat(
std::declval<std::tuple<ReadRequest>>(),
std::declval<std::conditional_t<InsertsAllowed,
std::tuple<InsertRequest>, std::tuple<>>>(),
std::declval<std::conditional_t<DeleletesAllowed,
std::tuple<DeleteRequest>, std::tuple<>>>()
));
public:
using RequestType = to_variant_t<RequestTypeTuple>;
// ...
};
评论