【发布时间】:2021-03-22 06:52:21
【问题描述】:
我最近一直在努力实现以函数式(管道)样式调用函数的方法,例如给定函数 foo(int, float) 可以以这种方式调用 10 | foo(10.f) 。
(这里假设管道算子,其实可以是随机的)
这是我所知道的
string _add(int&& a1, int&& a2)
{
return "ADD i:" + to_string(a1) + " i:" + to_string(a2);
}
string _add(float&& a1, int&& a2)
{
return "ADD f:" + to_string(a1) + " i:" + to_string(a2);
}
string _add(int&& a1, float&& a2)
{
return "ADD i:" + to_string(a1) + " f:" + to_string(a2);
}
struct add_name;
template <typename SUBJ, typename A1>
auto operator|(SUBJ subj, args<add_name, A1, monostate> args)
{
return _add(move(subj), move(args.a1));
}
template <typename A1> using add = args<add_name, A1, monostate>;
其中args 是一个保存参数的模板结构。
这允许我调用这样的函数
string s1 = 10.f | add(15);
string s2 = 10 | add(15);
string s3 = 10 | add(10.f);
最终有一个宏可以为每个函数名称生成模板,我能够非常成功地使用它。 此外,这对于重载和函数模板非常有效。
然而,这有一个巨大的缺点,即所有的函数特化都需要在定义操作符模板之前知道。
随着代码库的增长,它的使用变得越来越具有挑战性。
我一直在反复思考不同的想法,但存在 C++ 限制,无法以更有用的方式实现它,包括
- 无法将函数名沿模板特化链传递
- C++ 抱怨(重新)定义完全相同的模板
有没有办法实现如上所述的函数流水线?
【问题讨论】:
-
不清楚你想要什么,
args是什么。 -
你不能使用函子(有重载
operator())而不是函数。 -
“无法传递函数名”,通过名称传递重载集确实是不可能的,但是lambda可以用于。
-
在全局范围内
_add是一个保留符号。可能是导致某些问题的原因。 -
我已将此标记为需要更多详细信息。它需要一个可重现的例子。至少。
标签: c++ functional-programming template-specialization c++20