gpt4 book ai didi

c++17 通过生成预先声明的类型列表的笛卡尔积来制作 std::variant

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:26:24 26 4
gpt4 key购买 nike

假设我有一个包含三个模板类型参数的类。

template<typename Transformer, typename Criteria, typename Strategy>
struct ConfiguredPipeline {};

并且有以下类稍后在实例化 ConfiguredPipeline 时使用:

template<typename...>
struct CriteriaList
{
};
using SupportedCriteria = CriteriaList<ChiSquared, Cosine>;

template<typename...>
struct StrategiesList
{
};
using SupportedStrategies = StrategiesList<Voting>;

template<typename...>
struct TransformerList
{
};
using SupportedTransformer = TransformerList<AAGrouper11, AAGrouper15>;

我如何能够生成一个 std::variant 等价于:

using PipelineVariant = std::variant< 
ConfiguredPipeline< ChiSquared , Voting , AAGrouper11 > ,
ConfiguredPipeline< ChiSquared , Voting , AAGrouper15 > ,
ConfiguredPipeline< Cosine , Voting , AAGrouper11 > ,
ConfiguredPipeline< Cosine , Voting , AAGrouper15 >>;

通过简单地调用一个函数,例如:

using PipelineVariant = makeVariant< ConfiguredPipeline , SupportedCriteria , SupportedStrategies, SupportedTransformaers >;

最佳答案

我想 decltype()std::declval()std::tuple_cat() 可以帮到你很多。

给定以下声明的几个重载模板(注意:已声明,未定义,遵循 std::declval() 示例)函数来生成类型的笛卡尔积并折叠(感谢std::tuple_cat()) 在单个 std::tuple

template <template <typename...> class C, typename ... Ts>
constexpr std::tuple<C<Ts...>> tupleExpand (std::tuple<Ts...> const &);

template <template <typename...> class C, typename ... Ts,
template <typename...> class C0, typename ... Ls,
typename ... Cs>
constexpr auto tupleExpand (std::tuple<Ts...> const &, C0<Ls...> const &,
Cs const & ... cs)
-> decltype(std::tuple_cat(
tupleExpand<C>(std::declval<std::tuple<Ts..., Ls>>(), cs...)...));

和以下简单模板函数(同样:仅声明)将 std::tuple 类型转换为相应 std::variant 列表中的类型列表类型

template <typename ... Ts>
constexpr std::variant<Ts...> tupleToVariant (std::tuple<Ts...> const &);

你可以写一个MakeVariant类如下

template <template <typename...> class C, typename ... Ts>
struct MakeVariant
{
using type = decltype(tupleToVariant(std::declval<
decltype(tupleExpand<C>(std::declval<std::tuple<>>(),
std::declval<Ts>()...))>()));
};

还有一个简单的 using 助手

template <template <typename...> class C, typename ... Ts>
using MakeVariantType = typename MakeVariant<C, Ts...>::type;

你可以定义你的 PipelineVariant 类型如下

using PipelineVariant = MakeVariantType<ConfiguredPipeline,
SupportedCriteria,
SupportedStrategies,
SupportedTransformers>;

下面是一个完整的编译示例

#include <tuple>
#include <variant>

template <typename, typename, typename>
struct ConfiguredPipeline
{ };

struct ChiSquared {};
struct Cosine {};

template <typename...>
struct CriteriaList
{ };

using SupportedCriteria = CriteriaList<ChiSquared, Cosine>;

struct Voting {};

template <typename...>
struct StrategiesList
{ };

using SupportedStrategies = StrategiesList<Voting>;

struct AAGrouper11 { };
struct AAGrouper15 { };

template <typename...>
struct TransformerList
{ };

using SupportedTransformers = TransformerList<AAGrouper11, AAGrouper15>;

template <template <typename...> class C, typename ... Ts>
constexpr std::tuple<C<Ts...>> tupleExpand (std::tuple<Ts...> const &);

template <template <typename...> class C, typename ... Ts,
template <typename...> class C0, typename ... Ls,
typename ... Cs>
constexpr auto tupleExpand (std::tuple<Ts...> const &, C0<Ls...> const &,
Cs const & ... cs)
-> decltype(std::tuple_cat(
tupleExpand<C>(std::declval<std::tuple<Ts..., Ls>>(), cs...)...));

template <typename ... Ts>
constexpr std::variant<Ts...> tupleToVariant (std::tuple<Ts...> const &);

template <template <typename...> class C, typename ... Ts>
struct MakeVariant
{
using type = decltype(tupleToVariant(std::declval<
decltype(tupleExpand<C>(std::declval<std::tuple<>>(),
std::declval<Ts>()...))>()));
};

template <template <typename...> class C, typename ... Ts>
using MakeVariantType = typename MakeVariant<C, Ts...>::type;

using PipelineVariant = MakeVariantType<ConfiguredPipeline,
SupportedCriteria,
SupportedStrategies,
SupportedTransformers>;

int main ()
{
static_assert(std::is_same<PipelineVariant,
std::variant<ConfiguredPipeline<ChiSquared, Voting, AAGrouper11>,
ConfiguredPipeline<ChiSquared, Voting, AAGrouper15>,
ConfiguredPipeline<Cosine, Voting, AAGrouper11>,
ConfiguredPipeline<Cosine, Voting, AAGrouper15>>>::value);
}

关于c++17 通过生成预先声明的类型列表的笛卡尔积来制作 std::variant,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51696418/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com