6

I am writing a template class that wraps around member functions to reduce some calls - if some condition is true, the member function doesn't need to be called. The signature would look something like this

template <typename MemFuncType, MemFuncType> class MemberWrapper;

And I can specialize it thus:

template <typename R, typename T, R T::* MemFunc> class MemberWrapper<R T::*, MemFunc>{};

I would also like to restrict the number of arguments of R T::*. How do I do this?

The only solution I can think of is to implement a member functions traits class by providing partial specializations based on return type, function type, arguments list and cv-qualifiers. This would lead to a cumbersome implementation like the current std::mem_fn overloads. Is there a way of doing it better?

EDIT : Changed Ret to R. As pointed out in the comments, it isn't really the return type and the specialization was invalid.

Pradhan
  • 16,391
  • 3
  • 44
  • 59

2 Answers2

9

Don't try putting everything into one class. A member function is a function which is a member of a class. Hence start by creating some function traits class, e.g.

template< typename T >
class function_traits
{
  static_assert( sizeof( T ) == 0,
                 "function_traits<T>: T is not a function type" );
};

template< typename R, typename... Ts >
struct function_traits< R( Ts... ) >
{
  constexpr static const std::size_t arity = sizeof...( Ts );
  using result_type = R;
};

template< typename R, typename... Ts >
struct function_traits< R( Ts... ) const > : function_traits< R( Ts... ) > {};

template< typename R, typename... Ts >
struct function_traits< R( Ts... ) & > : function_traits< R( Ts... ) > {};

template< typename R, typename... Ts >
struct function_traits< R( Ts... ) const & > : function_traits< R( Ts... ) > {};

template< typename R, typename... Ts >
struct function_traits< R( Ts... ) && > : function_traits< R( Ts... ) > {};

template< typename R, typename... Ts >
struct function_traits< R( Ts... ) const && > : function_traits< R( Ts... ) > {};

With that, you can easily limit the number of arguments in your class:

template <typename Ret, typename T>
class MemberWrapper<Ret T::*>
{
  static_assert( function_traits<Ret>::arity <= 4,
                 "More than 4 arguments are not allowed" );
};

Live example

Daniel Frey
  • 55,810
  • 13
  • 122
  • 180
  • Does `R(Ts...)` match cv- or ref-qualified member functions? – dyp Jul 30 '14 at 19:24
  • (No it doesn't. But now I wonder why `std::remove_cv` doesn't remove those cv-qualifers.) – dyp Jul 30 '14 at 19:28
  • @dyp You are right, it does not. You need specializations like [this](http://coliru.stacked-crooked.com/a/27f4a552ade576e1). – Daniel Frey Jul 30 '14 at 19:29
  • @DanielFrey That starts to look like the `std::mem_fn` overloads set, which is what I want to avoid. – Pradhan Jul 30 '14 at 19:32
  • @Pradhan Updated the answer. In the end you will need to provide some overloads unless the standard library will provide something similar in the future. The important thing is to isolate this functionality *once* and reuse it in your code which should then not suffer from multiple overloads/specializations anymore. – Daniel Frey Jul 30 '14 at 19:36
  • Also, if you feel really generic, combinations with `volatile` :) And the thing with [`......`](http://stackoverflow.com/questions/14080539/weird-syntax-two-ellipsis-operators-in-parameter-pack-expansion) – jrok Jul 30 '14 at 19:40
  • @jrok Yeah, looks like I have some homework to do for my own library's `function_traits` :) – Daniel Frey Jul 30 '14 at 19:43
  • For reference, here are my own traits classes for [functions](https://github.com/iavr/ivl2/blob/master/include/ivl/root/core/type/traits/fun.hpp) and [members](https://github.com/iavr/ivl2/blob/master/include/ivl/root/core/type/traits/member.hpp). Typically, all qualifier combinations are 12, and I have specified that many specializations for three traits only (one for functions, two for members). Everything else is (hopefully) derived from there. – iavr Jul 30 '14 at 22:21
0

Boost Function Types provides a great collection of function traits. Also, this SO post shows examples.

Pradhan
  • 16,391
  • 3
  • 44
  • 59