In a template function I was trying to create a std::vector
with its value_type
being dependent on a member function of the template parameter to the function. This template parameter is restricted to being a vector containing unique pointers of a certain type with a certain function. For example:
/* somewhere in the code */
std::vector< std::unique_ptr< Widget > > myVec;
/* work with myVec and fill it, then call the relevant function */
func(myVec);
Now the function func
needs to retrieve the return type of the member function member_func
of Widget
. Note that Widget
can also be a different type, as long as it has the member function member_func
.
template <typename Vec>
void func(const Vec& vec) {
using ret_type = decltype(Vec::value_type::element_type::member_func()); // Doesn't work
std::vector< ret_type > local_vec;
}
I've tried various things, e.g. std::result_of
, std::invoke_result
and decltype
, but I can't seem to make it work. Is this even possible and if yes, how could it be achieved?
Is this close to what you wanted?
Demo: https://godbolt.org/g/dJkSf1
Explanation:
std::declval<typename Vec::value_type>()
generates a reference to a unique_ptr (which must be used in an unevaluated context). We then take the decltype of callinggenerated_reference->member_function()
.This would be the same type as the result of
vec[0]->member_func()
Indeed, we could write it this way:
Which might be more expressive and generic (
Vec
may now be any type which is vector-like and holds pointer-like things toFoo
)Furthermore, the more generically we approach the deduction, the more generic our
func
function becomes:Note
This code assumes that the return_type of
Foo::member_func
is not a reference type.If that's a possibility, we'd need to decide whether we used metaprogramming to:
a) convert reference types to std::reference_wrapper, so they can be stored in a vector, or
b) convert reference types to fundamental types using
std::decay
, which would result in copies being made.