The answer to this question picks apart a function type using a class template:
template <typename T>
struct function_args {};
template <typename R, typename... Args>
struct function_args<R(Args...)> {
using type = tuple<Args...>;
};
template <typename T>
using decltypeargs = typename function_args<T>::type;
As I studied what was being done here I tried to rewrite function_args
. I attempted to do this using a function so as to eliminate the need for the decltypeargs
template. But found myself mired in improper syntax:
template <typename T>
tuple<> myTry();
template <typename Ret, typename... Args>
tuple<Args...> myTry<Ret(Args...)>();
My hope had been to call decltype(myTry<decltype(foo)>())
to get the tuple
type instead of having to call decltypeargs<decltype(foo)>
. Is there a way to do this with a function declaration?
//------------------------ Machinery:
#include <tuple>
template< class Ret, class... Args >
std::tuple<Args...> m( Ret(Args...) );
//------------------------- Example:
#include <iostream>
#include <typeinfo>
void foo( double );
using namespace std;
auto main()
-> int
{
using Args_tuple = decltype( m( foo ) );
cout << typeid( Args_tuple ).name() << endl;
}
With a function, you can either just reuse the same type trait from before:
template <typename T>
function_args<T> myTry();
Or you can reimplement the same with functions. You can't partially specialize function templates, but you can overload:
namespace detail {
template <class T> struct tag { };
template <class R, class... Args>
tag<std::tuple<R, Args...>> myTry(tag<R(Args...)> );
template <class R, class C, class... Args>
tag<std::tuple<R, Args...>> myTry(tag<R(C::*)(Args...)> );
// etc.
}
template <typename T>
auto myTry() { return detail::myTry(detail::tag<T>{}); }
Functions cannot be specialized like that, but you don't need to specialize a function for this. Tested with gcc 6.1.1:
#include <iostream>
#include <tuple>
template <typename T> struct my_try;
template <typename Ret, typename... Args>
struct my_try<Ret(Args...)> {
std::tuple<Args...> operator()();
};
template<typename T>
auto MyTry()
{
return my_try<T>()();
}
void foo(int, char);
int main()
{
decltype(MyTry<decltype(foo)>()) t;
int *a= &std::get<0>(t);
char *b= &std::get<1>(t);
return 0;
}