我不确定标准是否允许我尝试的是什么,甚至可能没有意义,所以请务必随时纠正我。
我正在尝试将可变数量的std::function
对象传递给接受可变参数的函数,并且还接受可变参数模板参数。模板参数指定传入函数的返回类型。函数的签名如下所示:
template <typename ... TRets>
void DoStuff(std::function<TRets...()> funcs...)
我尝试做的是将传入的funcs
中的每一个的返回值传递给另一个以扩展值形式接受它们的函数。例如。 std::make_shared<TType>(funcs()...);
我正在使用带有--std=c++17
标志的g ++ 7.1.1,这会导致编译器出错。显然它不应该是错误的,但是标准中有什么说上面的代码是无效的吗?或许,是否有不同的语法来实现这一目标?
为了完整性,这里是一个最小的工作(对于一些工作的定义)例子:
#include <functional>
#include <memory>
class MyClass {
public:
int m_a;
double m_b;
MyClass(int a, double b) : m_a(a), m_b(b) {};
};
template <typename TReturn, typename ... Args>
std::shared_ptr<TReturn> CallFunctions(std::function<Args...()> funcs...) {
// Do stuff here
return std::make_shared<TReturn>(funcs()...);
}
int main(int argc, char * argv[]) {
auto x = CallFunctions<MyClass, int, double>(
[] () { return 5; },
[] () { return 3.14; }
);
return 0;
}
编辑以显示原始问题的更好意图
答案 0 :(得分:3)
template <class R, class... Args>
std::shared_ptr<R> CallFunctions(std::function<Args()>... funcs) {
return std::make_shared<R>( funcs()... );
}
这是C ++ 11。这是低效的。
template <class R, class... Args>
auto CallFunctions(Args&&... funcs)
-> decltype(std::make_shared<R>( funcs()... ))
{
return std::make_shared<R>( funcs()... );
}
删除了不必要的类型擦除,需要明确地传递返回类型。
如果你真的想传递返回类型:
template <class R, class... Args, class...Fs>
auto CallFunctions(Fs&&... funcs)
-> decltype(std::make_shared<R>( static_cast<Args>(funcs())... ))
{
return std::make_shared<R>( static_cast<Args>(funcs())... );
}
但我建议做上面的第二个解决方案。
答案 1 :(得分:0)
您可以使用C ++ 17 std::apply
在参数包的每个元素上使用std::invoke
。那么你不再需要std::function
了,因为std::invoke
只能调用可调用的对象,而且你不必再提供显式的模板参数(无论如何都是反模式)。作为奖励,您甚至可以检索被调用函数的返回值。
#include <functional>
#include <iostream>
#include <memory>
#include <tuple>
template < typename... R, typename... Args >
auto CallFunctions(Args... funcs) {
// Do stuff here
return std::apply(
[] (auto&&... x) {
return std::make_tuple(std::make_shared<R>(std::invoke(x))...);
}, std::make_tuple(funcs...)
);
}
int main() {
auto r = CallFunctions<int,double>(
[] () { return 5; },
[] () { return 3.14; }
);
std::cout << *std::get<0>(r) << ' ' << *std::get<1>(r) << '\n';
return 0;
}