I have a following not compiling code:
#include <iostream>
#include <type_traits>
template <typename T, typename... Args>
struct foo {};
template <typename T>
struct bar {
template <typename... Args>
auto func(Args... args)
{
return foo(*this, args...);
}
};
template <typename T, typename... Args>
using bar_func_return_type = std::invoke_result_t<&bar<T>::func, Args...>; // ERROR HERE
int main()
{
if constexpr (std::is_same_v<bar_func_return_type<int, float, double>, foo<int, floar, double>)
{
std::cout << "OK";
}
else {
std::cout << "FAIL";
}
return 0;
}
I am trying to get the result type of bar::func
method.
I get an error Template argument for template type parameter must be a type
when specifying bar_func_return_type
. How can I get the desired return type?
Looks like their are a lot of details missing from your code.
I tried to fix
them and get something that actually wants to compile.
Key ingredient to get return type =
template <typename T, typename... Args> using bar_func_return_type = decltype(std::declval<bar<T>>().func(std::declval<Args>()...));
Full code :
#include <iostream>
#include <type_traits>
template <typename T, typename... Args>
struct foo
{
// foo missed a constructor with correct types
foo(const T&, Args&&...)
{
};
};
template <typename T>
struct bar
{
// Args&& is a bit more flexible in practice
template <typename... Args>
auto func(Args&&... args)
{
return foo<bar,Args...>(*this, std::forward<Args>(args)...);
}
};
// std::declval makes default instances ot the types specified
// this is usually how I deduce return values (could be invoke_result_t is actually a bit more easy to use.
template <typename T, typename... Args>
using bar_func_return_type = decltype(std::declval<bar<T>>().func(std::declval<Args>()...));
int main()
{
using retval_t = bar_func_return_type<int, float, double>;
// No need to do a runtime check, you can already
// test at compile time using static_assert
static_assert(std::is_same_v<retval_t, foo<bar<int>, float, double>>);
return 0;
}