I wrote a test framework for testing function output (see code below).
template <class FuncTy, class... IndexType>
typename std::enable_if<std::tuple_size<typename function_helper<FuncTy>::arguments>::value == sizeof...(IndexType)
and std::is_same_v<typename function_helper<FuncTy>::return_type, AnswerTy>
and not is_member_function_pointer_v<FuncTy>, void>::type
test(FuncTy func, IndexType... arg_indexes) {
using function_args_tuple = typename function_helper<FuncTy>::arguments;
using function_return_type = typename function_helper<FuncTy>::return_type;
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
function_args_tuple params; /// error is here
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/// .....
}
It works well for functions that do not have references in arguments.
e.g.:
- for fucntion
int f(int x, vector<int> y);
(i.e., no references in argument list), the type ofparams
is astd::tuple<int, vector<int>>
, so theparams
can instantiate normally with code above, - but for functions like
int f(int& x, vector<int>& y);
(i.e., one or more references in argument list), the type ofparams
becomesstd::tuple<int&, vector<int>&>
, which is not able to instantiate with code above.
The type of the tuple params
is affected by argument list of a function (done with another function), the type of the tuple is undefined, so I just cannot do like this and this, since both of the solutions in the two links use a make_tuple
explictly and an instantiated tuple object.
So my question is how to remove the references without instantiate the tuple. (e.g., make tuple<int&, vector<int>&>
to tuple<int, vector<int>>
).
Or else if there is some ways to instantiate a tuple with references in the tuple's template argument list without hard-coded make_tuple
calls.
CodePudding user response:
You can get the element type of the tuple
through template partial specialization and apply std::decay
to those types to remove references, something like this
#include <type_traits>
#include <tuple>
template<class Tuple>
struct decay_args_tuple;
template<class... Args>
struct decay_args_tuple<std::tuple<Args...>> {
using type = std::tuple<std::decay_t<Args>...>;
};
Then you can get a tuple
of the decay argument types through the helper class
decay_args_tuple<decltype(function_args_tuple)>::type params;
Note that the argument type is still required to be default constructible.