问题
I want to make a function object which takes arbitrary function objects and returns a tuple which stores the return value of each function object.
To achieve this goal, I made a class A
class A
{
private:
template <class Ret, class Func>
auto impl(Ret ret, Func func) -> decltype(tuple_cat(ret, make_tuple(func())))
{
return tuple_cat(ret, make_tuple(func()));
}
template <class Ret, class First, class... Funcs>
auto impl(Ret ret, First first, Funcs... funcs)
-> decltype(impl(tuple_cat(ret, make_tuple(first())), funcs...))
{
return impl(tuple_cat(ret, make_tuple(first())), funcs...);
}
public:
template <class Func>
auto operator()(Func func) -> decltype(make_tuple(func()))
{
return make_tuple(func());
}
template <class First, class... Funcs>
auto operator()(First first, Funcs... funcs)
-> decltype(impl(make_tuple(first()),funcs...))
{
impl(make_tuple(first()),funcs...);
}
};
And in the main function, I made three lambdas.
int main(){
auto func1 = [](){ cout << 1 << endl; return 1;};
auto func2 = [](){ cout << 2 << endl; return 2;};
auto func3 = [](){ cout << 3 << endl; return 3;};
A a;
auto x = a(func1, func2);
cout << "ans : " << get<0>(x) << get<1>(x) << endl; // I expect ans : 12
}
This code can be compiled by gcc 4.7.2. However, it doesn't work as I expected. How should I modify this code?
回答1:
I think the problem is that you're missing a return
statement:
template <class First, class... Funcs>
auto operator()(First first, Funcs... funcs)
-> decltype(impl(make_tuple(first()),funcs...))
{
return impl(make_tuple(first()),funcs...);
// ^^^^^^
}
Without it, your code has Undefined Behavior. Per Paragraph 6.6.3/2 of the C++11 Standard:
[...] Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
回答2:
The obvious problem is that you've a missing return statement as pointed out by other answer.
Anyway, I think you have done too much. This should work:
class A
{
public:
template <class First, class... Funcs>
auto operator()(First first, Funcs... funcs) -> decltype((make_tuple(first(),funcs()...)))
{
return (make_tuple(first(),funcs()...));
}
};
int main(){
auto func1 = [](){ cout << 1 << endl; return 1;};
auto func2 = [](){ cout << 2 << endl; return 2;};
A a;
auto x = a(func1, func2);
cout << "ans : " << get<0>(x) << get<1>(x) << endl; // I expect ans : 12
}
Online Demo
回答3:
@Andy's fix works, but you can do it a lot simpler than that, without implementing overloads nor helper functions:
#include <iostream>
#include <tuple>
template<typename... Args>
auto tuple_from_funs(Args&&... args) -> std::tuple<decltype(args())...>{
return std::make_tuple(args()...);
}
int f() { return 1; }
char g() { return '2'; }
std::string h() { return "jorge"; }
int main() {
auto tup = tuple_from_funs(f, g, h);
std::cout << std::get<0>(tup) << ", " << std::get<1>(tup) << ", " << std::get<2>(tup) << std::endl;
}
Demo here.
来源:https://stackoverflow.com/questions/15059250/make-variadic-function-which-takes-arbitary-functors-and-returns-a-tuple-of-each