Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to understand this Template parameter

Maybe it's flu, or I'm just plain stupid, but I can't understand a part of this Crow framework code. My inner C++ parser fails.

template <typename MW>
struct check_before_handle_arity_3_const
{
 template <typename T,
     //this line
     void (T::*)(int, typename MW::context&) const = &T::before_handle 
  >
    struct get
    { };
};

I know it's a template parameter inside template declaration. It looks like maybe some lambda or function pointer type parameter... but, I'm not sure. Can someone explain this line?

Update: Exploring depths of newly obtained knowledge - after the answer was given - led me to this excerpt from a great book:

A template can accept a pointer to a function as a nontype template parameter. (Most often in this book, nontype template parameters are integral values.) [...] Using a pointer to a function as a nontype template argument means that we no longer need to store it in the map. This essential aspect needs thorough understanding. The reason we don't need to store the pointer to a function is that the compiler has static knowledge about it. Thus, the compiler can hardcode the function address in the trampoline code.

So, now I know one of the reasons to use this technique.

like image 775
strangeqargo Avatar asked Dec 18 '22 13:12

strangeqargo


2 Answers

void (T::*)(int, typename MW::context&) const is a non-type template parameter. It is a pointer to a member function of T.

With the use of = &T::before_handle, its default value is set to &T::before_handle.

like image 123
R Sahu Avatar answered Dec 24 '22 01:12

R Sahu


The reason I used this technique is to support 2 kinds of handler format: https://github.com/ipkn/crow/blob/master/include/middleware.h#L17

check_before_handle_arity_3_const is used here:

    template <typename T>
    struct is_before_handle_arity_3_impl
    {
        template <typename C>
        static std::true_type f(typename check_before_handle_arity_3_const<T>::template get<C>*);

        template <typename C>
        static std::true_type f(typename check_before_handle_arity_3<T>::template get<C>*);

        template <typename C>
        static std::false_type f(...);

    public:
        static const bool value = decltype(f<T>(nullptr))::value;
    };

With SFINAE, is_before_handle_arity_3_impl<T>::value is determined whether we can call the handler with 3 arguments or not. By using std::enable_if, Crow can call the proper handler: https://github.com/ipkn/crow/blob/master/include/http_connection.h#L110

like image 28
ipkn Avatar answered Dec 24 '22 02:12

ipkn