Reputation:
I'm trying to make a function that takes a function and a vector and applies the function to the arguments from the vector, something like
f([](int x, int y) {return x+y;}, {1, 2}); \\returns 3
my current code looks like this:
#include <iostream>
#include <vector>
#include <functional>
#include <type_traits>
#include <boost/type_traits.hpp>
template <std::size_t... Indices>
struct indices {
using next = indices<Indices..., sizeof...(Indices)>;
};
template <std::size_t N>
struct build_indices {
using type = typename build_indices<N-1>::type::next;
};
template <>
struct build_indices<0> {
using type = indices<>;
};
template <std::size_t N>
using BuildIndices = typename build_indices<N>::type;
template <size_t num_args>
struct unpack_caller
{
private:
template <typename FuncType, size_t... I>
typename std::result_of<FuncType>::type call(FuncType &f, std::vector<int> &args, indices<I...>){
return f(args[I]...);
}
public:
template <typename FuncType>
typename std::result_of<FuncType>::type operator () (FuncType &f, std::vector<int> &args)
{
return call(f, args, BuildIndices<num_args>{});
}
};
template<typename InnerType, typename ...Args>
class MFA
{
std::function<InnerType(Args...)> func;
public:
MFA(InnerType f(Args...))
: func(f)
{}
virtual InnerType calc(std::vector<InnerType> & x)
{
return unpack_caller<sizeof...(Args)>()(func, x);
}
};
int main()
{
auto fun1 = MFA<int, int, int>([](int x, int y) {return x + y; });
std::vector<int> arg = std::vector<int>({1, 2});
fun1.calc(arg);
return 0;
}
and it gives an error (GCC 4.8.1):
$g++ -std=c++0x main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
main.cpp: In instantiation of 'InnerType MFA<InnerType, Args>::calc(std::vector<InnerType>&) [with InnerType = int; Args = {int, int}]':
main.cpp:68:18: required from here
main.cpp:57:50: error: no match for call to '(unpack_caller<2ul>) (std::function<int(int, int)>&, std::vector<int>&)'
return unpack_caller<sizeof...(Args)>()(func, x);
^
main.cpp:25:8: note: candidate is:
struct unpack_caller
^
main.cpp:35:45: note: template<class FuncType> typename std::result_of<FuncType>::type unpack_caller<num_args>::operator()(FuncType&, std::vector<int>&) [with FuncType = FuncType; long unsigned int num_args = 2ul]
typename std::result_of<FuncType>::type operator () (FuncType &f, std::vector<int> &args)
^
main.cpp:35:45: note: template argument deduction/substitution failed:
main.cpp: In substitution of 'template<class FuncType> typename std::result_of<FuncType>::type unpack_caller<num_args>::operator()(FuncType&, std::vector<int>&) [with FuncType = FuncType; long unsigned int num_args = 2ul] [with FuncType = std::function<int(int, int)>]':
main.cpp:57:50: required from 'InnerType MFA<InnerType, Args>::calc(std::vector<InnerType>&) [with InnerType = int; Args = {int, int}]'
main.cpp:68:18: required from here
main.cpp:35:45: error: invalid use of incomplete type 'class std::result_of<std::function<int(int, int)> >'
In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/move.h:57:0,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:59,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/stl_algobase.h:64,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/char_traits.h:39,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/ios:40,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/ostream:38,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/iostream:39,
from main.cpp:1:
/usr/local/gcc-4.8.1/include/c++/4.8.1/type_traits:1878:11: error: declaration of 'class std::result_of<std::function<int(int, int)> >'
class result_of;
How can I correct it? The function MFA::calc
must have the type it has now as MFA is supposed to be an implementation of an interface.
EDIT: I've been using code from following stackoverflow questions: Any Solution to Unpack a Vector to Function Arguments in C++? Initialize std::array with a range (pair of iterators)
Upvotes: 1
Views: 366
Reputation: 56863
You can't use std::result_of<FuncType>::type
, you would need to add the arguments, e.g. std::result_of<FuncType(int,int)>::type
. In your case, this is a more difficult than the alternative, hence I suggest you use:
template <size_t num_args>
struct unpack_caller
{
private:
template <typename FuncType, size_t... I>
auto call(FuncType &f, std::vector<int> &args, indices<I...>)
-> decltype( f(args[I]...) )
{
return f(args[I]...);
}
public:
template <typename FuncType>
auto operator () (FuncType &f, std::vector<int> &args)
-> decltype( std::declval<unpack_caller<num_args>>().call(f, args, BuildIndices<num_args>{}) )
{
return call(f, args, BuildIndices<num_args>{});
}
};
Note that with C++14, you could leave out the -> decltype(...)
part and simply rely on auto
alone.
Upvotes: 1