条件变体类型取决于类模板参数

问题描述 投票:0回答:1

我有一个类模板,本质上想为将公开给 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
。另外,我想避免堆叠一堆条件来实现我的目标,以防我需要添加更多模板参数来达到类似的效果。

c++ templates metaprogramming
1个回答
0
投票

首先,您需要创建一个元函数,以有条件地将另一种类型附加到

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>;
        using RequestType = condit_append_t<DeletesAllowed,Type2, DeleteRequest>;
         //...
    };
© www.soinside.com 2019 - 2024. All rights reserved.