2017-07-19 239 views
1

我不确定标准允许我尝试什么,甚至可能没有意义,所以通过一切手段随时纠正我。使用可变参数类型参数的变量函数

我试图将一个可变数量的std::function对象传递给接受可变参数的函数,并接受可变参数模板参数。模板参数指定返回类型中进行传递的功能函数的签名看起来像这样:

template <typename ... TRets> 
void DoStuff(std::function<TRets...()> funcs...) 

什么我试图做的是从每个funcs传入的传递返回值到另一个以扩展价值形式接受它们的函数。例如。 std::make_shared<TType>(funcs()...);

我正在使用g ++ 7.1.1和--std=c++17标志,导致编译器发生故障。很明显,它不应该排除故障,但是标准中是否有上述代码无效的内容?或者,是否有不同的语法来完成这个目标?

为了完整起见,这里是一个最低限度的工作(对工作的一些定义)例如:

#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

你到底想干什么? – Justin

+0

如果编译器出现故障,您可能需要提交错误报告。 – Justin

+0

您是否期望每个传递给'CallFunctions'的函数都不带任何参数并返回一个值? – Justin

回答

2
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())...); 
} 

,但我建议做上面的第二个解决方案。

+0

这足够接近我需要的东西,请编辑C++ 17示例以使用'funcs()...'语法调用函数,我会接受。我编辑了原文,以更清楚地解释我的意图。 'CallFunctions'函数的主体然后变成'return std :: make_shared (funcs()...);'。我会接受这个答案,当它已被编辑 – Howard

+0

@howard我不认为'funcs()...;'是有效的C++ 17;做了什么改变?啊,我明白了,编辑的问题。 – Yakk

+0

我可以收集的最好的是,这个语法被参数包扩展所覆盖:'pattern ....'如[这里]概述的(http://en.cppreference.com/w/cpp/language/parameter_pack) – Howard

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; 
} 

Live example