c++17通过生成预先声明的类型列表的笛卡尔乘积来生成std::变体
c++17 making std::variant by generating cartesian product of pre-declared lists of types
假设我有一个由三个模板类型参数组成的类。
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
中生成类型的笛卡尔乘积并折叠(由于std::tuple_cat()
(
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>()...))>()));
};
和一个简单的CCD_ 12辅助
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);
}
相关文章:
- 如何比较自定义类的std::变体
- 通过网络、跨平台传递std::变体是否安全
- 访问列表中的所有 std::变体,并为每次访问捕获附加值
- 如何将 boost::hana::tuple 转换为 std::变体
- 如何多态地使用替代类型的 std::变体
- c++17通过生成预先声明的类型列表的笛卡尔乘积来生成std::变体
- std变体和正向声明
- std::变体与 std::nullptr_t 内部的比较
- 操作员||STD ::变体的过载
- STD ::变体和不完整类型:它如何工作
- 如何通过std ::变体正确替换boost ::变体
- 如何将std ::变体减少到一个值
- 获取std ::元组元素作为std ::变体
- 将STD ::变体转换为STD ::模板类实例的元组
- 如何使用%类型指令使用std ::变体类型
- 我可以将Brad-Init-list用于STD ::变体的向量吗?
- 获取std ::变体的基础类型
- 使用std :: unique_ptr的子类与std ::变体
- STD ::访问与STD ::变体的工作
- 请求C 17的编译器通过使用-STD 17标志在-STD = C 17时,将启用STD ::变体的支持