Skip to content

Instantly share code, notes, and snippets.

@tomilov
Created October 6, 2015 05:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomilov/6fb555b32a36d3bdc7a1 to your computer and use it in GitHub Desktop.
Save tomilov/6fb555b32a36d3bdc7a1 to your computer and use it in GitHub Desktop.
using enable_if as return type of lambda function
#include <type_traits>
#include <utility>
#include <iostream>
#include <cassert>
#include <cstdlib>
namespace details
{
template< typename visitor, typename ...visitors >
struct composite_visitor
: std::decay_t< visitor >
, composite_visitor< visitors... >
{
using std::decay_t< visitor >::operator ();
using composite_visitor< visitors... >::operator ();
composite_visitor(visitor && _visitor, visitors &&... _visitors)
: std::decay_t< visitor >(std::forward< visitor >(_visitor))
, composite_visitor< visitors... >{std::forward< visitors >(_visitors)...}
{ ; }
};
template< typename visitor >
struct composite_visitor< visitor >
: std::decay_t< visitor >
{
using std::decay_t< visitor >::operator ();
composite_visitor(visitor && _visitor)
: std::decay_t< visitor >(std::forward< visitor >(_visitor))
{ ; }
};
}
template< typename visitor, typename ...visitors >
details::composite_visitor< visitor, visitors... >
compose_visitors(visitor && _visitor, visitors &&... _visitors)
{
return {std::forward< visitor >(_visitor), std::forward< visitors >(_visitors)...};
}
#define PP { std::cout << __PRETTY_FUNCTION__ << std::endl; }
struct A
{
A() = default;
A(A &&) PP
A(A const &&) PP
A(A &) PP
A(A const &) PP
};
int
main()
{
auto const l = [] (auto && arg) -> std::enable_if_t< std::is_lvalue_reference< decltype(arg) >{}, int >
{
static_assert(std::is_lvalue_reference< decltype(arg) >{});
return std::is_const< std::remove_reference_t< decltype(arg) > >{} ? 1 : 0;
};
{
A v;
A const c{};
assert(l(v) == 0);
assert(l(c) == 1);
}
auto const r = [] (auto && arg) -> std::enable_if_t< std::is_rvalue_reference< decltype(arg) >{}, int >
{
static_assert(std::is_rvalue_reference< decltype(arg) >{});
return std::is_const< std::remove_reference_t< decltype(arg) > >{} ? 3 : 2;
};
{
A v;
A const c{};
assert(r(std::move(v)) == 2);
assert(r(std::move(c)) == 3);
}
auto const lr = compose_visitors(l, r);
{
A v;
A const c{};
assert(lr(v) == 0);
assert(lr(c) == 1);
assert(lr(std::move(v)) == 2);
assert(lr(std::move(c)) == 3);
}
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment