Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does this C++ template macro mean?

Can somebody please break down this for me? I know macros, and I am fairly familiar with templates, but I have no idea what the author is expressing with this. What's the intended usage, why is it written like this? What are we defining to be what here? How and why does one use this?

#define MY_CLASS(RET_TYPE, ... )\
    template<typename Derived>\
    __VA_ARGS__\
    RET_TYPE my_class_impl<Derived>

And I also have something like

MY_CLASS( )::my_class_impl( int arg_id )

And I also see

template<typename Derived>
class my_class_impl

I heard from a colleague that this is a case of CRTP (curiously recurring template pattern), but he did not have any more specific insights.

Also, I see it used subsequently as follows:

MY_CLASS(some_type)::find_desired_val(int x) {
// some code
}

So, the macro is used to substitute method signatures for the class my_class_impl when actually implementing them?

like image 497
Baron Yugovich Avatar asked Aug 11 '15 14:08

Baron Yugovich


2 Answers

It's used to define member functions of my_class_impl<Derived>.

MY_CLASS(void)::member(Bar b) {}

Expands to :

template <typename Derived>
void my_class_impl<Derived>::member(Bar b) {}

The variadic macro arguments can be used for various (standard or not) attributes, such as __declspec(...), [[...]], etc. For example:

MY_CLASS(void, __declspec(dllexport))::foo();

Expands to :

template <typename Derived>
__declspec(dllexport) void my_class_impl<Derived>::foo() {}

The MY_CLASS()::my_class_impl(int arg_id), thanks to a compiler extension that allows missing macro parameters (present on MSVC, as well as Clang and GCC, I was mistaken), expands to a constructor :

template <typename Derived>
/* nothing */ my_class_impl<Derived>::my_class_impl(int arg_id) {}

It is also quite an ugly macro. Not only is it hard to understand, it hides away very mundane stuff, and breaks if you ever try to return a type containing a comma (std::map<int, int>).

like image 104
Quentin Avatar answered Sep 29 '22 10:09

Quentin


The RET_TYPE is a hint that this is a function, and MY_CLASS in particular hints at member functions. Those can be declared static as well.

Less common would be [[noreturn]] or [[deprecated]] which are C++14 attributes.

The <Derived> part is pretty irrelevant to this, class templates can have member functions just like classes can.

like image 24
MSalters Avatar answered Sep 29 '22 10:09

MSalters