8

I have a question involving functional template arguments to template classes in C++.

I'd like to define a template class Foo taking a single template parameter Fun

   template <typename Fun>
   struct Foo {
      ...
   };

such that given a function like

   void bar(std::string a, float b, char c)
   {
      ...
   }

then Foo<bar>::args_t will be equivalent to a typedef for

   std::tuple<std::string, float, char>

Is this possible? (The use of std::tuple here is just for concreteness. More generally I'm wondering if it's possible to do something like pattern-matching on the arguments of a functional template parameter.)

The point is to avoid having to define Foo in a way like

   template Foo<typename A, typename B, typename C, typename D,
      D (*Fun)(A a, B b, C c)>
   struct Foo {
      typedef std::tuple<A,B,C>  args_t;
   };

which requires both committing to a fixed number of function arguments, and requiring the argument and return types of the function to be provided explicitly as template parameters. (Defining Foo using variadic templates could presumably solve the former issue, but what about the latter?)

Thanks!

Constructor
  • 7,273
  • 2
  • 24
  • 66
factotum
  • 348
  • 3
  • 9
  • Look into variadic templates. Also you might want to avoid naming types with `_t` as they are reserved in POSIX. – user657267 Jul 25 '14 at 04:58
  • 1
    @user657267 I'm quite aware of variadic templates, and mentioned them in my question. The comment about naming types with `_t` seems to be a bit out of left field. – factotum Jul 25 '14 at 05:25
  • That's why it's a comment and not an answer. – user657267 Jul 25 '14 at 05:26

1 Answers1

13

Declare a primary template and leave it unimplemented.

template<typename T>
struct foo;     // unimplemented primary template

Then provide a partial specialization that matches function types as the template argument.

template<typename Result, typename... Args>
struct foo<Result(Args...)>
{
    using args_t = std::tuple<Args...>;
};

You can access the nested type as

foo<decltype(bar)>::args_t

Live demo

Praetorian
  • 106,671
  • 19
  • 240
  • 328