Today, we'll be going into the fun things you can do with templates! Now even though Chili has already covered the basics of templates, the world of template metaprogramming is far more vast than one video can cover! Today, we are going to explore ways templates can simplify code through type based referencing. Let's say that you want to create a Graphics class that can make different graphic objects and return their ids to the user. Likewise, those graphic objects can be returned to be reused by other users. Without any template metaprogramming, it'll usually look like so:
Code: Select all
class Graphics
{
public:
using Id = size_t;
class Sprite
{
public:
Sprite ( ) = default;
void Render ( ) const
{
std::cout << "Sprite rendered!" << '\n';
}
};
class Text
{
public:
Text ( ) = default;
void Render ( ) const
{
std::cout << "Text rendered!" << '\n';
}
};
Graphics ( ) = default;
Id CreateSprite ( )
{
//recycle unused sprites
if ( unused_sprites_.empty ( ) )
{
const auto id = sprites_.size ( );
sprites_.emplace_back ( );
return id;
}
else
{
const auto id = unused_sprites_.back ( );
unused_sprites_.pop_back ( );
return id;
}
}
Id CreateText ( )
{
//recycle unused texts
if ( unused_texts_.empty ( ) )
{
const auto id = texts_.size ( );
texts_.emplace_back ( );
return id;
}
else
{
const auto id = unused_texts_.back ( );
unused_texts_.pop_back ( );
return id;
}
}
void DeleteSprite ( const Id id )
{
//save the sprite for reuse
unused_sprites_.push_back ( id );
//reset the sprite
sprites_ [ id ] = { };
}
void DeleteText ( const Id id )
{
//save the text for reuse
unused_texts_.push_back ( id );
//Reset the text
texts_ [ id ] = { };
}
Sprite& GetSprite ( const Id id )
{
return sprites_ [ id ];
}
Text& GetText ( const Id id )
{
return texts_ [ id ];
}
private:
std::vector<Sprite> sprites_;
std::vector<Id> unused_sprites_;
std::vector<Text> texts_;
std::vector<Id> unused_texts_;
};
Code: Select all
template<typename Type>
Create( );
Introducing: Tuples!
Code: Select all
std::tuple<int, double, std::string> tuple = std::make_tuple ( 12, 3., "#LeninDidNothingWrong" );
std::cout << std::get<int> ( tuple ) << '\n';
std::cout << std::get<double> ( tuple ) << '\n';
std::cout << std::get<2> ( tuple ) << '\n';
Code: Select all
template<typename Resource>
class ResourceManager
{
public:
using ResourceContainer = std::vector<Resource>;
using Id = typename ResourceContainer::size_type;
using IdContainer = std::vector<Id>;
ResourceManager ( ) = default;
Id Create ( )
{
//recycle unused resources
if ( unused_resources_.empty ( ) )
{
const auto id = resources_.size ( );
resources_.emplace_back ( );
return id;
}
else
{
const auto id = unused_resources_.back ( );
unused_resources_.pop_back ( );
return id;
}
}
void Delete ( const Id id )
{
//save the resource for reuse
unused_resources_.push_back ( id );
//reset the resource
resources_ [ id ] = { };
}
Resource& Get ( const Id id )
{
return resources_ [ id ];
}
private:
ResourceContainer resources_;
IdContainer unused_resources_;
};
Code: Select all
class Graphics
{
public:
class Sprite
{
public:
Sprite ( ) = default;
void Render ( ) const
{
std::cout << "Sprite rendered!" << '\n';
}
};
class Text
{
public:
Text ( ) = default;
void Render ( ) const
{
std::cout << "Text rendered!" << '\n';
}
};
class Mesh
{
public:
Mesh ( ) = default;
void Render ( ) const
{
std::cout << "Mesh rendered!" << '\n';
}
};
class Isosurface
{
public:
Isosurface ( ) = default;
void Render ( ) const
{
std::cout << "Isosurface rendered!" << '\n';
}
};
Graphics ( ) = default;
template<typename Type>
auto Create ( )
{
return std::get<ResourceManager<Type>> ( resource_managers_ ).Create ( );
}
template<typename Type>
void Delete ( const typename ResourceManager<Type>::Id id )
{
std::get<ResourceManager<Type>> ( resource_managers_ ).Delete ( id );
}
template<typename Type>
auto& Get ( const typename ResourceManager<Type>::Id id )
{
return std::get<ResourceManager<Type>> ( resource_managers_ ).Get ( id );
}
private:
std::tuple<
ResourceManager<Sprite>,
ResourceManager<Text>,
ResourceManager<Mesh>,
ResourceManager<Isosurface>
> resource_managers_;
};