Code: Select all
class Input
{
public:
Input() = default;
template<typename T>
Input( T&& _value )
:
data( std::move( _value ) )
{}
void ReadData( std::ifstream& is )
{
auto read_data = [ & ]( auto& _data )
{
_data.ReadData( is );
};
std::visit( read_data, data );
}
void SaveData( std::ostream& os )const
{
auto write_data = [ & ]( const auto& _data )
{
_data.SaveData( os );
};
std::visit( write_data, data );
}
template<typename T, typename IfSame, typename IfNotSame>
void ConditionalCall( IfSame&& _ifsame, IfNotSame&& _ifnotsame )
{
auto call = [ & ]( auto& _data )
{
using type = std::decay_t<decltype( _data )>;
if constexpr( std::is_same_v<type, T> )
{
_ifsame(_data);
}
else
{
_ifnotsame();
}
};
std::visit( call, data );
}
private:
InputData data;
};
Code: Select all
Input* ptr = recordList.GetBack();
if (ptr)
{
ptr->ConditionalCall<DelayData>(
[ delay ]( DelayData& _data )
{
_data.AddDelay( delay );
}, [ delay ]()
{
recordList.AddEventToRecord<DelayData>( delay );
} );
}
Had to make a few changes to get it to accept the single Input interface instead of using the overloaded visitor structs. For common cases like serializing and deserializing, the interface feels like a polymorphic type, but in special cases like DelayData::AddDelay, it feels foreign. I suppose you could also just put the AddDelay in the Input class:
Code: Select all
bool AddDelay( float _delay )
{
auto add_delay = [_delay]( auto& _data )
{
using type = decay_t<decltype(_data)>;
if constexpr( std::is_same_v<type, DelayData> )
{
_data.AddDelay( _delay );
return true;
}
return false;
};
return std::visit( add_delay, data );
}
// Then this code becomes
Input* ptr = recordList.GetBack();
if (ptr)
{
if( !ptr->AddDelay( delay ) )
recordList.AddEventToRecord<DelayData>( delay );
}