use*_*934 6 c++ generics higher-kinded-types variadic-templates higher-rank-types
我正在开发一个相对简单的程序(实际上是一个计算器).但是,我决定尽可能使我的程序的所有组件都是通用的,因为:
作为该计划的一部分,我正在使用Tuple我正在编写的课程.我知道一个类已经存在,但我喜欢完全控制我的代码,这只是一个练习.
我需要做的一件事是将表达式元组(表达式本身是通用的)转换为包含表达式求值结果的元组.简而言之,我(遗漏了一些琐碎的部分):
template <class T>
class Expression {
public:
virtual T Eval() = 0;
// ...
};
template <class First, class ... Rest>
class Tuple {
// ...
private:
First first;
Tuple<Rest ...> rest;
};
Run Code Online (Sandbox Code Playgroud)
我想专门研究像这样的泛型类型的元组:
template <template <class> class R, class First, class ... Rest>
class Tuple<R<First>, R<Rest> ...> {
// and here is the problem:
Tuple<First, Rest ...> Transform(function<template<class T> T(R<T>)>);
};
Run Code Online (Sandbox Code Playgroud)
之后我可以这样做:
template <class T> // There has to be a better way to do this
T Eval(Expression<T>& expr){
return expr.Eval();
}
// ...
Tuple<First, Rest ...> tuple = exprs.Transform(Eval);
Run Code Online (Sandbox Code Playgroud)
在这里有几个地方,我不知道如何去做事情,一个可以帮助我在这里的真正的专家将不胜感激.我希望这段代码不会因为小错误而编译,但这不是重点 - 我主要担心的是我标记的行.如果我从短暂的时期内正确地回忆起我学会了Haskell这个函数应该是Rank-2(如果没有请注释,我将删除标签).它看起来不对劲.有没有办法做到这一点?
更新:
我被建议尝试传递一个带有泛型operator ()作为模板参数的仿函数,但这也不起作用.
我认为你可以非常简单地做到这一点,根本不需要 C++14。我将假设有关 your 的Tuple构建方式的一些事情,即这两个因素存在:
Tuple(First, Rest... ); // (1)
Tuple(First, const Tuple<Rest...>& ); // (2)
Run Code Online (Sandbox Code Playgroud)
我们需要一种类型特征:给定一个我们要转换的函数,我们需要知道它产生什么类型:
template <typename T, typename F>
using apply_t = decltype(std::declval<F>()(std::declval<T>()));
Run Code Online (Sandbox Code Playgroud)
(天哪,我爱 C++11)
这样,我们就可以轻松确定返回类型,只需递归调用该函数即可:
template <typename First, typename... Rest>
struct Tuple
{
template <typename F>
Tuple<apply_t<First, F>, apply_t<Rest, F>...>
Transform(F func)
{
return {func(first), rest.Transform(func)}; // hence the need
// for ctor (2)
};
};
Run Code Online (Sandbox Code Playgroud)
(根据您的编写方式,Tuple您可能需要也可能不需要仅返回 a 的简单转换的基本情况Tuple<>,或者仅返回 a 的基本情况Tuple<apply_t<First, F>>。无论哪种方式,都没什么大不了的)。
而且您甚至根本不需要专门化Tuple。您只需要传递正确的函子即可。例如:
struct Zero
{
template <typename T>
int operator()(T ) { return 0; }
};
struct Incr
{
template <typename T>
T operator()(T x) { return x + 1; }
};
Tuple<int, double, char> tup(1, 2.0, 'c');
auto z = tup.Transform(Zero{}); // z is Tuple<int, int, int>{0, 0, 0}
auto i = tup.Transform(Incr{}); // i is Tuple<int, double, char>{2, 3.0, 'd'}
Run Code Online (Sandbox Code Playgroud)
这是一个完整的代码示例,也记录了所有类型。当然,使用 C++14,我们可以内联执行这些操作:
auto i2 = tup.Transfom([](auto x) -> decltype(x) {return x+1; });
// i2 is a Tuple<int, double, char>{2, 3.0, 'd'};
// without the trailing decltype, it gets deduced as Tuple<int, double, int>.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
379 次 |
| 最近记录: |