A A*_*laa 6 c++ templates template-meta-programming variadic-templates c++17
假设我有一个三个模板类型参数的类.
template<typename Transformer, typename Criteria, typename Strategy>
struct ConfiguredPipeline {};
Run Code Online (Sandbox Code Playgroud)
并在以后的实例化中使用以下类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>;
Run Code Online (Sandbox Code Playgroud)
我怎样才能生成std::variant
相当于:
using PipelineVariant = std::variant<
ConfiguredPipeline< ChiSquared , Voting , AAGrouper11 > ,
ConfiguredPipeline< ChiSquared , Voting , AAGrouper15 > ,
ConfiguredPipeline< Cosine , Voting , AAGrouper11 > ,
ConfiguredPipeline< Cosine , Voting , AAGrouper15 >>;
Run Code Online (Sandbox Code Playgroud)
通过简单地调用如下函数:
using PipelineVariant = makeVariant< ConfiguredPipeline , SupportedCriteria , SupportedStrategies, SupportedTransformaers >;
Run Code Online (Sandbox Code Playgroud)
我假设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...)...));
Run Code Online (Sandbox Code Playgroud)
和以下简单模板函数(再次:仅声明)转换std::tuple
类型列表中的类型std::variant
列表
template <typename ... Ts>
constexpr std::variant<Ts...> tupleToVariant (std::tuple<Ts...> const &);
Run Code Online (Sandbox Code Playgroud)
你可以写一个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>()...))>()));
};
Run Code Online (Sandbox Code Playgroud)
并有一个简单的using
帮手
template <template <typename...> class C, typename ... Ts>
using MakeVariantType = typename MakeVariant<C, Ts...>::type;
Run Code Online (Sandbox Code Playgroud)
您可以PipelineVariant
按如下方式定义类型
using PipelineVariant = MakeVariantType<ConfiguredPipeline,
SupportedCriteria,
SupportedStrategies,
SupportedTransformers>;
Run Code Online (Sandbox Code Playgroud)
以下是完整的编译示例
#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);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
280 次 |
最近记录: |