Code: Select all
#include <iostream>
#include <variant>
void do_int( int ) { std::cout << "do_int chosen\n"; }
using TestVar = std::variant<int, double, float>;
template<typename T>
class Switch
{
public:
Switch( T& value )
:
var( value )
{}
template<typename MatchType, typename CaseBlock, typename...Args>
Switch& Case( CaseBlock block, Args&&...args )
{
auto memberfn_call = [ & ]( auto& var_, auto& object, auto&&...args_ )
{
( object.*block )( var_ );
};
std::visit( [&]( auto& var_ )
{
using type = std::decay_t<decltype( var_ )>;
if constexpr( std::is_same_v<type, MatchType> )
{
if constexpr( std::is_member_function_pointer_v<CaseBlock> )
{
memberfn_call(
std::forward<decltype( var_ )>( var_ ),
std::forward<Args>( args )...
);
}
else
{
block( std::forward<Args>(args)..., std::forward<type>( var_ ) );
}
}
}, var );
return *this;
}
private:
T& var;
};
struct ATest
{
void operator()( double d ) { std::cout << "ATest::operator() chosen\n"; }
void do_float( float f ) { std::cout << "ATest::do_float chosen\n"; }
};
int main()
{
TestVar v = 42.0;
ATest atest;
Switch{ v }
.Case<int>( do_int )
.Case<double>( atest )
.Case<float>( &ATest::do_float, atest );
v = 420;
Switch{ v }
.Case<int>(do_int)
.Case<double>( atest )
.Case<float>( &ATest::do_float, atest );
return 0;
}
Code: Select all
Output:
ATest::operator() chosen
do_int chosen
Works with free function pointers, member function pointers functors and lambdas.
A few weeks ago I said I wanted something like a switch statement on types:
Code: Select all
switch<type>( v )
{
case<int>:
case<double>:
case<float>:
}