gpt4 book ai didi

c++ - 绑定(bind)元函数 : accept both types and template template parameters (accept anything)

转载 作者:太空狗 更新时间:2023-10-29 19:45:38 27 4
gpt4 key购买 nike

我正在尝试编写一个 Bind 元编程模板辅助元函数,将模板参数绑定(bind)到某物。

我有一个简单的模板元函数的工作实现:

template<typename T0, typename T1>
struct MakePair
{
using type = std::pair<T0, T1>;
};

template<template<typename...> class TF, typename... Ts>
struct Bind
{
template<typename... TArgs>
using type = TF<Ts..., TArgs...>;
};

using PairWithInt = typename Bind<MakePair, int>::type;
static_assert(std::is_same<PairWithInt<float>, MakePair<int, float>>{}, "");

但是如果 MakePair 的模板参数是模板模板呢?还是简单的数值?

template<template<typename> class T0, template<typename> class T1>
struct MakePair0
{
using type = /*...*/;
};

template<template<typename...> class TF, template<typename> class... Ts>
struct Bind0 { /*...*/ }

// ...

template<int T0, int T1>
struct MakePair1
{
using type = /*...*/;
};

template<template<int...> class TF, int... Ts>
struct Bind1 { /*...*/ }

很多不必要的重复。如果模板参数在类型、模板模板和整型常量之间混合,就会变得难以管理。

类似下面的代码是否可行?

template<template<ANYTHING...> class TF, ANYTHING... Ts>
struct BindAnything
{
template<ANYTHING... TArgs>
using type = TF<Ts..., TArgs...>;
};

ANYTHING 将接受类型、模板模板、模板模板模板、整数值等...

最佳答案

当我进行严肃的元编程时,我会将一切变成类型。

template<class T>struct tag{using type=T;};
template<class Tag>using type_t=typename Tag::type;

template<template<class...>class> struct Z {};
template<class Z, class...Ts>
struct apply {};
template<template<class...>class z, class...ts>
struct apply< Z<z>, ts... >:
tag< z<ts...> >
{};
template<class Z, class...Ts>
using apply_t = type_t< apply<Z, Ts...> >;

现在我们通过 template<?> foo大约为 Z<foo> , 它现在是一种类型。

可以对常量做类似的事情,使用 std::integral_constant<T, t> (并且更容易使用相同的别名),或 template<class T, T* p> struct pointer_constant {}; ,通过将它们转化为类型。

一旦一切都是类型,您的元编程就会变得更加统一。模板只是成为一种类型,apply_t做事。

在 C++ 中没有办法拥有可以是类型、值或模板的模板参数。所以这是您能得到的最好的。

不是为上述模式编写的模板需要被包装起来,并且它们的参数“提升”为类型。例如:

template<class T, class t>
using number_constant = std::integral_constant< T, t{} >;
using number_constant_z = Z<number_constant>;

已将其参数从值“提升”为类型,然后用 Z 包裹起来把自己变成一个类型。

现在绑定(bind)读取:

template<class z, class... Ts>
struct Bind {
template<class... More>
using type_base = apply_t< z, Ts..., More... >;
using type = Z<type_base>;
};
template<class Z, class...Ts>
using Bind_t = type_t<Bind<Z,Ts...>>; // strip ::type
using Bind_z = Z<Bind_t>; // quote into a Z<?>

Bind_z是一个包装模板的类型,它返回一个包装模板,并将一个包装模板的类型作为它的第一个参数。

使用方法:

template<class...>struct types{using type=types;};
using types_z=Z<types>;

template<class...Ts>
using prefix =apply_t< Bind_z, types_z, Ts... >;
using prefix_z = Z<prefix>;

prefix_z采用一组类型,并生成 types<?...> 的工厂将包含前缀 Ts...首先。

apply_t< apply_t< prefix_z, int, double, char >, std::string >

types< int, double, char, std::string >

live example .

还有另一种有趣的方法:在函数中进行元编程:

template<template<class...>class z, class...Ts>
constexpr auto apply_f( Z<z>, tag<Ts>... )
-> tag<z<Ts...>> { return {}; }

在这里,类型由类型 tag<t> 的值表示, 模板 Z<z>值为 std::integral_constant<?> .

这两个:

template<class T>
constexpr tag<T> Tag = {};
template<template<class...>class z>
constexpr Z<z> Zag = {};

为您提供获取分别表示类型和模板的值的方法。

#define TYPEOF(...) type_t<decltype(__VA_ARGS__)>

是从 tag 的实例移动的宏输入标签,然后输入 Tag<?>从类型移动到标签的实例。

TYPEOF( apply_f( apply_f( Zag<prefix>, Tag<int>, Tag<double>, Tag<char> ), Tag<std::string> ) )

apply_t< apply_t< prefix_z, int, double, char >, std::string >

奇怪,但可能很有趣。

关于c++ - 绑定(bind)元函数 : accept both types and template template parameters (accept anything),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32056649/

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