Created
March 22, 2018 03:36
-
-
Save LB--/82cd3947fc98a9481ff14bac23b412a0 to your computer and use it in GitHub Desktop.
I'm working on an implementation of std::overload. This version requires that you specify the argument types for the callables, but it works on anything that can be called. Also handles const-correctness thanks to SFINAE. If you comment out line 69, GCC optimizes it to `return 10;`: https://godbolt.org/g/2GFgFX
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <variant> | |
namespace impl | |
{ | |
template<typename T, typename Callable> | |
struct Overload | |
{ | |
Callable callable; | |
auto operator()(T &t) noexcept(noexcept(callable(t))) | |
{ | |
return callable(t); | |
} | |
auto operator()(T const &t) noexcept(noexcept(callable(t))) | |
{ | |
return callable(t); | |
} | |
auto operator()(T &t) const noexcept(noexcept(callable(t))) | |
{ | |
return callable(t); | |
} | |
auto operator()(T const &t) const noexcept(noexcept(callable(t))) | |
{ | |
return callable(t); | |
} | |
}; | |
template<typename... Bases> | |
struct Overloads final | |
: Bases... | |
{ | |
using Bases::operator()...; | |
}; | |
} | |
template<typename... Types, typename... Callables> | |
auto overload(Callables &&... callables) noexcept(noexcept(impl::Overloads<impl::Overload<Types, Callables>...>{callables...})) | |
{ | |
static_assert(sizeof...(Types) == sizeof...(Callables)); | |
return impl::Overloads<impl::Overload<Types, Callables>...>{callables...}; | |
} | |
int main() | |
{ | |
using variant_t = std::variant<char, short, int, double>; | |
short v = 0; | |
auto visitor = overload<char, short, int, double> | |
( | |
[](char const v) | |
-> int | |
{ | |
return v+1; | |
}, | |
[](short v) | |
-> int | |
{ | |
return v+10; | |
}, | |
+[](int &v) | |
-> int | |
{ | |
return v+100; | |
}, | |
[=](double) mutable | |
-> int | |
{ | |
return v += 1000; | |
} | |
); | |
v = visitor(v); | |
variant_t var {v}; | |
v += std::visit(visitor, var); | |
return v; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment