hae*_*lix 11 c++ templates bind metaprogramming currying
这更像是一个概念性问题.我正在尝试找到将两个arg模板(参数类型)转换为一个arg模板的最简单方法.即,绑定其中一种类型.
这将是bindboost/std中的元编程等价物.我的例子包括一个可能的用例,即std::is_same作为模板参数传递给一个模板,该模板采用一个arg模板模板参数(std::is_same是一个双arg模板),即TypeList::FindIf.在TypeList没有完全在这里实现,也不是FindIf,但你的想法.它采用"一元谓词"并返回该谓词为真的void类型,如果不是这样的类型.
我有两个工作变体,但第一个不是单行,第二个使用相当冗长的BindFirst装置,这对非类型模板参数不起作用.有没有一种简单的方法来编写这样的单行程?我相信我正在寻找的程序被称为currying.
#include <iostream>
template<template<typename, typename> class Function, typename FirstArg>
struct BindFirst
{
template<typename SecondArg>
using Result = Function<FirstArg, SecondArg>;
};
//template<typename Type> using IsInt = BindFirst<_EqualTypes, int>::Result<Type>;
template<typename Type> using IsInt = std::is_same<int, Type>;
struct TypeList
{
template<template<typename> class Predicate>
struct FindIf
{
// this needs to be implemented, return void for now
typedef void Result;
};
};
int main()
{
static_assert(IsInt<int>::value, "");
static_assert(!IsInt<float>::value, "");
// variant #1: using the predefined parameterized type alias as predicate
typedef TypeList::FindIf<IsInt>::Result Result1;
// variant #2: one-liner, using BindFirst and std::is_same directly
typedef TypeList::FindIf< BindFirst<std::is_same, int>::Result>::Result Result2;
// variant #3: one-liner, using currying?
//typedef TypeList::FindIf<std::is_same<int, _>>::Result Result2;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
单击此处查看在线编译器GodBolt中的代码.
我认为执行此操作的典型方法是将所有内容保留在类型世界中。不要采用模板模板——它们很混乱。让我们编写一个名为的元函数ApplyAnInt,它将采用“元函数类”并应用于int它:
template <typename Func>
struct ApplyAnInt {
using type = typename Func::template apply<int>;
};
Run Code Online (Sandbox Code Playgroud)
一个简单的元函数类可能只是检查给定类型是否为int:
struct IsInt {
template <typename T>
using apply = std::is_same<T, int>;
};
static_assert(ApplyAnInt<IsInt>::type::value, "");
Run Code Online (Sandbox Code Playgroud)
现在的目标是支持:
static_assert(ApplyAnInt<std::is_same<_, int>>::type::value, "");
Run Code Online (Sandbox Code Playgroud)
我们能做到这一点。我们将调用包含_“lambda 表达式”的类型,并编写一个名为 的元函数lambda,它将转发一个不是 lambda 表达式的元函数类,或者生成一个新的元函数(如果它是):
template <typename T, typename = void>
struct lambda {
using type = T;
};
template <typename T>
struct lambda<T, std::enable_if_t<is_lambda_expr<T>::value>>
{
struct type {
template <typename U>
using apply = typename apply_lambda<T, U>::type;
};
};
template <typename T>
using lambda_t = typename lambda<T>::type;
Run Code Online (Sandbox Code Playgroud)
所以我们更新我们原来的元函数:
template <typename Func>
struct ApplyAnInt
{
using type = typename lambda_t<Func>::template apply<int>;
};
Run Code Online (Sandbox Code Playgroud)
现在剩下两件事:我们需要is_lambda_expr和apply_lambda。这些实际上并没有那么糟糕。对于前者,我们将查看它是否是类模板的实例化,其中类型之一是_:
template <typename T>
struct is_lambda_expr : std::false_type { };
template <template <typename...> class C, typename... Ts>
struct is_lambda_expr<C<Ts...>> : contains_type<_, Ts...> { };
Run Code Online (Sandbox Code Playgroud)
对于apply_lambda,我们只需将 替换_为给定类型:
template <typename T, typename U>
struct apply_lambda;
template <template <typename...> class C, typename... Ts, typename U>
struct apply_lambda<C<Ts...>, U> {
using type = typename C<std::conditional_t<std::is_same<Ts, _>::value, U, Ts>...>::type;
};
Run Code Online (Sandbox Code Playgroud)
这就是您实际上所需要的。我会将其扩展为支持,arg_<N>作为读者的练习。