【发布时间】:2023-03-07 14:19:01
【问题描述】:
我正在尝试编写一个通用函数,它连接两个可以使用同一组参数调用的函数,但我遇到了一些麻烦。这是我到目前为止所拥有的(它无法编译)
//A functor to store the input functions and call them
template <typename LEFT, typename RIGHT>
struct combine_functions {
combine_functions(const LEFT &left, const RIGHT &right)
: left(left), right(right) {}
template <typename ...ARGS>
std::enable_if_t<
//My compiler doesn't have support for C++17 std library so I
//found an implementation of callable on SO
is_callable_v<LEFT, std::decay_t<ARGS>...> &&
is_callable_v<RIGHT, std::decay_t<ARGS>...>
> operator()(ARGS... args) const {
//the return value doesn't matter in my situation and can be
//completely discarded
left(std::forward<ARGS>(args)...);
right(std::forward<ARGS>(args)...);
}
private:
mutable LEFT left;
mutable RIGHT right;
};
//I should probably have an enable if that checks the arguments
//are function pointers or functors
template <typename LEFT, typename RIGHT>
combine_functions<
std::decay_t<LEFT>,
std::decay_t<RIGHT>
>
operator+(
const LEFT &left,
const RIGHT &right
) {
return {left, right};
}
如果不清楚我要达到的目标,那么这里是一个测试。
#include <iostream>
#include "combine functions.hpp"
struct A {
void operator()(float &f, int i) {
std::cout << "running A with float " << f << " and int " << i << '\n';
f++;
}
};
struct B {
void operator()(float &f, int i) {
std::cout << "running B with float " << f << " and int " << i << '\n';
f++;
}
};
struct C {
void operator()(float &f, int i) {
std::cout << "running C with float " << f << " and int " << i << '\n';
f++;
}
};
int main(int, const char**) {
A a;
B b;
C c;
auto abc = concat(concat(a, b), c);
//or
//auto abc = a + b + c;
std::function<void(float &, int)> abcFunc = abc;
float f = 5.0f;
int i = 9;
abcFunc(f, i);
return EXIT_SUCCESS;
}
这是预期的输出
running A with float 5 and int 9
running B with float 6 and int 9
running C with float 7 and int 9
- 如何在 C++ 中实现这一点?
- 在这种情况下使用重载运算符是否不明智?
- “连接”是此操作的最佳术语吗?
【问题讨论】:
-
enable_if_t基本上是没必要的。发布无法编译的内容,出现错误 -
您使用的是什么编译器,遇到了什么错误?一个可疑的部分(在编译时不会影响任何东西)是在同一个参数上使用
std::forward两次 - 如果第一个函数消耗一个右值,那么第二个函数就没有任何东西了。 -
请提供minimal reproducible example,包括您使用的任何第三方代码。不完整的片段是没有意义的。错误可能在任何地方。
-
@n.m.通常是的。我认为这是可以接受的,因为 OP 不知道 如何 处理此代码。就期望的结果而言,这是最少且有据可查的,并且他们在尝试解决问题时表现出了尽职调查。
-
您的 operator+ 将适用于所有类型的对象,甚至是不可调用的对象。这可能是您想要 enable_if 的地方。但是为您没有创建的任何类创建重载运算符通常是不好的做法,并且您没有编写 std::function 类或函数指针“类”,所以我会完全放弃它。此外,我希望
(f+g)()与f()+g()相同;见function spaces on Wikipedia
标签: c++ templates lambda variadic-templates