DEV Community

That `overloaded` Trick: Overloading Lambdas in C++17

Tamir Bahar on August 15, 2017

C++17 has granted us with std::variant. Simply put, it is a type-safe union. To access the value it stores, you can either request a specific type ...
Collapse
 
mmatrosov profile image
Mikhail Matrosov • Edited

It would be nice to mention why we changed () to {} when we switched to deduction guide. E.g. if you add constructor

overloaded(Ts... ts) : Ts(ts)... {}

then you can use () again. At least I was curious about this.

Collapse
 
tmr232 profile image
Tamir Bahar

I did mention that we need to use aggregate initialization. Though I now think my reasoning for it is wrong. Also - I never tried making it work with ().

Collapse
 
misiaszek profile image
Marcin Misiaszek • Edited

This also works without deduction guide:

template<class... Ts> struct overload : Ts... {
  overload(Ts...) = delete;
  using Ts::operator()...;
};
Thread Thread
 
maxxon profile image
Ma-XX-oN

I'm confused with this part:

        Print{ // (2)
            [](const char* str) { puts(str); },
            [](int i) { printf("%d\n", i); }
        }

The braces indicate a constructor call, but there is none. There is a non-member helper template though, but it has no body. So, what's happening here?

Thread Thread
 
maxxon profile image
Ma-XX-oN

It's not a non-member helper template, it's a user defined deduction guide. See this article:

arne-mertz.de/2017/06/class-templa...

Thread Thread
 
misiaszek profile image
Marcin Misiaszek

It works also without deduction guide and the 'using' fix is for g++. 'operator()' cannot be ambiguous in visitors but gcc is very careful with overloading derived functions. In clang we can easily have the same results with minimal code (checked output assembler with Compiler Explorer):

template<class... Ts> struct overload : Ts... {
  overload(Ts...) = delete;
};

There is needed aggregate Initialisation + variadic templates.

Collapse
 
voins profile image
Alexey Voinov

Very cool code transformations. :) Thank you.

Collapse
 
void78 profile image
void78

Excellent brake-down, ta!

Collapse
 
trueqbit profile image
klaus triendl

You don't need using Ts::operator()...;

Collapse
 
stanlukanoff profile image
Stanimir Lukanov

That's just... weird...
PS: (...) this in the comment is not fold expression

Collapse
 
tmr232 profile image
Tamir Bahar

What's weird?

Collapse
 
stanlukanoff profile image
Stanimir Lukanov

Where the standard is going to :) nevertheless the implementation is cool!

Collapse
 
mmatrosov profile image
Mikhail Matrosov

(2) and (3) in second code snippet are mixed up.

Collapse
 
tmr232 profile image
Tamir Bahar

Fixed. Thank you!