# Kill min/max macros!

### Kill min/max macros!

I guess by now we all know that macros suck. Nevertheless, sometimes you just have to work with them unknowingly, i.e. if a library does spooky stuff like this:

#ifndef max
#define max(a,b)  (((a) < (b)) ? (b) : (a))
#endif
#ifndef min
#define min(a,b)  (((a) < (b)) ? (a) : (b))
#endif


For my thesis, I'm working with an embedded system. Now, there exists the concept of unaddressed data, namely 'streams'. A library simulation of a stream that is functionally equivalent looks like this:

template<typename T>
struct stream
{
private:
std::deque<T> data;
public:
void write(T v) { data.push_back(v); }
T read()        { auto tmp = data.front(); data.pop_back(); return tmp; }

bool empty() const { return data.empty(); }
};


Guess what: It is really, really bad to read() inside of those 'nice' macros min/max. The following snippets may quickly yield a segmentation fault, depending on the amount of data present in the stream.

int maximum = 0;
while(!stream.empty())


Just something we need to be aware of. :-(

# The ubiq trick

### ubiq-trick

First things first: I want to make clear that I did not come up with this. However, I got inspired by Antony Polukhin, who gave a talk at meetingcpp 2018 about his Boost.Pfr library. There is some voodoo-tmp-blackmagic going on in there in order to implement reflections without macros nor external tooling within C++14, so check it out.

#### A motivating example

Coincidentally, this trick was just recently used by Peter Dimov on the C++ slack chat after Will Wray posted a motivating challenge: Implement the metafunction nttp_t in the following code:

template<int> struct int_constant {};
template<char> struct char_constant {};

template<template<auto> typename T>
using nttp_t = /* TODO: Make this int for T=int_constant. */


It should evaluate to int if we pass int_constant to it and char if we pass char_constant to it.

There are several ways to implement this. Probably anyone who has worked with a bit of template trickery before would be able to somehow hardcode this, but we really want it to work in a more generic environment. Just think of a my_absurd_constant that was declared later, right after the nttp_t. You certainly can't hardcode that in a reliable way. (Note that my_absurd_constant can take only primitive types as non-type template parameter, though, as of pre-C++20)

#### The solution

Functions have template argument deduction (mostly because you don't want to provide the template arguments for i.e. operator<< when you print something), so a first idea can be to use a rather crippled 'type function' match:

template<auto X, template<auto> class T>
auto match(T<X>) -> decltype(X);


As we can deduce all template arguments just with the one parameter of type T<X>, this should actually work out just fine: decltype(match(int_constant<42>{})).

And it does work out just fine as it evaluates to type int, which is precisely what we want!

In order to "invoke" match now with some arbitrary Trait, we can utilize Antony's "ubiq-trick" to get the type out of the templated value parameter. First, we define us a struct ubiq like so:

inline constexpr struct ubiq
{
template<class T>
constexpr operator T () const
{ return T{}; }
} ubiq_;


The struct itself does nothing, however, it has one special property: A constexpr, templated conversion operator, which means whenever we use ubiq_ it can be implicitly converted to any default constructible type T. Thus, it can also be converted to the type of the value which is anonymous within the template argument list of Trait. This is actually the reason why we need all this trickery, because we can't just simply do template<template<auto X> class Trait> using nttp_t = decltype(X)! (try it) Finally, we are able to define nttp_t with it:

template<template<auto> class Trait>
using nttp_t = decltype(match(Trait<ubiq_>{}));


#### Full code

this->~dasnacl();