#include #include #include "AftrOpenGLIncludes.h" namespace Aftr { //Scott Nykl -- See IndexedGeometry_TE.h for an example of how to use this efficient, elegant, //safe IndexedGeometry (over the earlier memory-error prone IndexedGeometry*). class IndexedGeometry_TEIFace //type erased methods any drawable must implement { public: /// PRIMARY INTERFACE supported by this IndexedGeometry_TEIFace... No virtual methods specified here /// at all. void render() const noexcept { if( ptr ) return ptr->render(); } void renderGL32() const noexcept { if( ptr ) return ptr->renderGL32(); } void renderCompatibility() const noexcept { if( ptr ) return ptr->renderCompatibility(); } void renderSelection( GLubyte red, GLubyte green, GLubyte blue ) const noexcept { if( ptr ) return ptr->renderSelection( red,green,blue); } //----Implementation details that give "intelligent" copy and move behaviors /// MyModelTE const& m = typeErased.get_erased_type(); template const T& get_erased_type() const { const T& ref = static_cast&>(*this->ptr).obj; return ref; } /// MyModelTE const& m = typeErased.get_erased_type(); template T& get_erased_type() { T& ref = static_cast&>(*this->ptr).obj; return ref; } operator bool() const noexcept { return this->ptr != nullptr; } bool empty() const noexcept { return (*this) ? true : false; } IndexedGeometry_TEIFace() : ptr( nullptr ) { //std::cout << LOC << ": ctor\n"; } ~IndexedGeometry_TEIFace() { //std::cout << LOC << ": ~IndexedGeometry_TEIFace\n"; } template struct decay_equiv : std::is_same::type, U>::type {}; template< typename T, typename U > inline static constexpr bool decay_equiv_v = decay_equiv< T, U >::value; template IndexedGeometry_TEIFace( T&& moveT ) noexcept requires( !decay_equiv_v ) //Case where IndexedGeometry_TEIFace( T&& ) is called with a T such that T is NOT another IndexedGeometry_TEIFace { //std::cout << LOC << ": tmpl move ctor\n"; ptr = std::unique_ptr( new ModelTE( std::forward( moveT ) ) ); } template< typename T> //supports use case for IndexedGeometry_TEIFace p = std::move(myCircle); IndexedGeometry_TEIFace& operator=( T&& toMoveT ) requires( !decay_equiv_v ) //const& where T is NOT a IndexedGeometry_TEIFace { //std::cout << LOC << ": tmpl operator= && move assign\n"; ptr = std::unique_ptr( new ModelTE( std::forward( toMoveT ) ) ); return *this; } template< typename T> //supports use case for IndexedGeometry_TEIFace p{ a_const_Square } }; //Square is a T IndexedGeometry_TEIFace( T const& copyT ) requires(!decay_equiv_v) //const& where T is NOT a IndexedGeometry_TEIFace { //std::cout << LOC << ": tmpl copy ctor\n"; ptr = std::unique_ptr( new ModelTE( copyT ) ); } template< typename T> //supports use case for IndexedGeometry_TEIFace p{ a_non_const_Square } }; //Square is a T IndexedGeometry_TEIFace( T& copyT ) requires(!decay_equiv_v) //const& where T is NOT a IndexedGeometry_TEIFace { //std::cout << LOC << ": tmpl copy ctor\n"; ptr = std::unique_ptr( new ModelTE( copyT ) ); } template< typename T> //supports use case for IndexedGeometry_TEIFace p = Square{}; //Square is a T IndexedGeometry_TEIFace& operator=( T const& copyT ) requires(!decay_equiv_v) //const& where T is NOT a IndexedGeometry_TEIFace { //std::cout << LOC << ": tmpl operator= copy assign ctor\n"; ptr = std::unique_ptr( new ModelTE( copyT ) ); return *this; } IndexedGeometry_TEIFace( IndexedGeometry_TEIFace const& toCopy ) //supports use case for const IndexedGeometry_TEIFace& ref = v[0]; IndexedGeometry_TEIFace z( ref ); { //std::cout << LOC << "Vanilla copy ctor IndexedGeometry_TEIFace( IndexedGeometry_TEIFace const& toCopy )...\n"; this->ptr = toCopy.ptr ? toCopy.ptr->clone() : nullptr; } IndexedGeometry_TEIFace( IndexedGeometry_TEIFace&& toMove ) noexcept { //std::cout << LOC << ": Mov ctor...\n"; this->ptr = std::move( toMove.ptr ); toMove.ptr = nullptr; }; IndexedGeometry_TEIFace& operator=( IndexedGeometry_TEIFace const& toCopyAssign ) { std::printf( "%s: WARNING copyAssignClone issued, expensive operation if each frame...\n", AFTR_FILE_LINE_STR ); if( this != &toCopyAssign ) this->ptr = toCopyAssign.ptr ? toCopyAssign.ptr->clone() : nullptr; return *this; } IndexedGeometry_TEIFace& operator=( IndexedGeometry_TEIFace&& toMoveAssign ) noexcept { if( this != &toMoveAssign ) { this->ptr = std::move( toMoveAssign.ptr ); toMoveAssign.ptr = nullptr; } return *this; } private: struct Concept { /// PRIMARY INTERFACE supported by this IndexedGeometry_TEIFace... all methods should be virtual virtual void render() const noexcept = 0; virtual void renderGL32() const noexcept = 0; //and duplicate the interface in this Concept virtual void renderCompatibility() const noexcept = 0; virtual void renderSelection( GLubyte red, GLubyte green, GLubyte blue ) const noexcept = 0; virtual std::unique_ptr clone() const = 0; // Done w/ PRIMARY INTERFACE Concept& operator=( Concept const& toCopyAssign ) = delete; Concept& operator=( Concept&& toMoveAssign ) = delete; Concept( Concept const& toCopy ) = delete; Concept( Concept&& toMove ) noexcept = delete; Concept() = default; virtual ~Concept() = default; }; std::unique_ptr ptr; template< typename T > struct ModelTE : public Concept { ModelTE& operator=( ModelTE const& toCopyAssign ) = delete; ModelTE& operator=( ModelTE&& toMoveAssign ) noexcept = delete; ModelTE() = delete; ModelTE( T const& toCopy ) : obj( toCopy ) { //std::cout << LOC << ": ModelTE copy ctor...\n"; } ModelTE( T&& value ) noexcept : obj( std::forward( value ) ) { //std::cout << LOC << ": ModelTE move ctor...\n"; } virtual ~ModelTE() { //std::cout << LOC << ": ~ModelTE...\n"; } //PRIMARY INTERFACE------------- virtual void render() const noexcept override { obj.render(); }; virtual void renderGL32() const noexcept override { obj.renderGL32(); }; virtual void renderCompatibility() const noexcept override { obj.renderCompatibility(); } virtual void renderSelection( GLubyte red, GLubyte green, GLubyte blue ) const noexcept override { obj.renderSelection( red,green,blue ); } //Requires that T is copy-able virtual std::unique_ptr clone() const override { T copy( obj ); return std::make_unique( std::forward(copy) ); } //PRIMARY INTERFACE------------- T obj; using type = T; }; }; }