#include <iostream>
#include <string>
#include <memory>
#include <utility>
#include <cassert>
#define GENERATE_META(type) \
public: \
static const MetaInfo& StaticMeta() \
{ \
static MetaInfo meta{#type}; \
return meta; \
}
struct MetaInfo
{
const std::string _id;
explicit MetaInfo( std::string ti )
: _id{std::move( ti )}{}
bool operator==(const MetaInfo& rhs) const
{
return _id == rhs._id;
}
bool operator!=(const MetaInfo& rhs) const
{
return operator==(rhs);
}
};
// Inheritance is just for example
// In real project code is generated by tools
struct Base
{
protected:
Base() = default;
};
struct MyType1 : Base
{
GENERATE_META(MyType1)
int _dummy = 1;
};
struct MyType2 : Base
{
GENERATE_META(MyType2)
float _dummy = 2.f;
};
struct MyType3 : Base
{
GENERATE_META(MyType3)
std::string _dummy = "gg";
};
class Table
{
public:
template< typename T >
static Table Create()
{
auto data = std::make_shared<T>();
auto meta = &T::StaticMeta();
return { data, meta };
}
const std::shared_ptr<Base>& Data() const{ return _data; }
const MetaInfo& Meta() const{ return *_meta; }
private:
Table( std::shared_ptr<Base> data, const MetaInfo * meta )
: _data{std::move(data)}
, _meta{meta}
{}
private:
std::shared_ptr<Base> _data;
const MetaInfo * const _meta = nullptr;
};
template< typename T >
void Print( const Table& table )
{
assert( table.Meta() == T::StaticMeta() );
const auto& data = *static_cast<T*>(table.Data().get());
std::cout << table.Meta()._id << " -> " << data._dummy << "\n";
}
/////////////////////////////////////////////////////////////////////
template< typename T >
bool Validate( const Table& table )
{
if ( table.Meta() == T::StaticMeta() )
{
Print<T>( table );
return true;
}
return false;
}
template< typename T, typename ...Tables >
bool Validate( const Table& table )
{
if ( Validate<T>( table ) )
return true;
return Validate<Tables...>(table);
}
int main()
{
const auto t1 = Table::Create<MyType1>();
const auto t2 = Table::Create<MyType2>();
const auto t3 = Table::Create<MyType3>();
const auto r1 = Validate<MyType1, MyType2>(t1);
assert( r1 );
const auto r2 = Validate<MyType1, MyType2>(t2);
assert( r2 );
const auto r3 = Validate<MyType1, MyType2>(t3);
assert( !r3 );
return 0;
}