include/globject.hpp
f085ab64
 /// Guards
 
 #ifndef GLOBJECT_HPP_
 #define GLOBJECT_HPP_
 
 
 /// Includes
 
 #include <string>
 
 #include <glbase.hpp>
 #include <gltraits.hpp>
 
 
 /// GLObject
 
 template<GLenum object_type>
 class GLObject;
 
 template<>
 class GLObject<0> : protected GLBase
 {
 
 protected:
 
     //// Object
 
     std::string static label_(
         GLenum object_type,
         GLuint object
     );
     void static label_(
         GLenum              object_type,
         GLuint              object,
         std::string const & label
     );
 
     //// Name
 
     std::string static name_(
         GLenum              object_type,
         GLuint              object,
         std::string const & label = {}
     );
 
 };
 
 template<GLenum object_type>
 class GLObject
 :
     public    GLObject<0>,
     protected GLTraits::Object<object_type>
 {
 
 public:
 
     //// Special member functions
 
     template<typename... Args>
     explicit GLObject(std::string const & label, Args... args)
     try
     :
         object_{0}
     {
         if (debug() >= 2)
             this->debug_action_("construct", name_(object_type, 0, label));
         this->gen_objects(1, &object_, args...);
         try
         {
             // Strictly speaking `glObjectLabel` needs a *created* object.
             // `glGen*s` does not create objects (`glCreate*` does though), it
             // just reserves names for them. *Binding* that name for the first
             // time creates the object. Therefore, the below is not guaranteed
             // to work, but seems to on most drivers... Forcing our subclasses
             // to bind the name and call us back to set the label is deemed too
             // inconvenient so here we are.
             label_(object_type, object_, label);
             check_error_(glGetError());
         }
         catch (...)
         {
             this->delete_objects(1, &object_);
             object_ = 0;
             throw;
         }
     }
     catch (...)
     {
         this->fail_action_("construct", name_(object_type, 0, label));
     }
 
     ~GLObject()
     {
         if (debug() >= 2)
             debug_action_("destroy");
         this->delete_objects(1, &object_);
     }
 
     GLObject(GLObject && other) noexcept
     :
         object_{other.object_}
     {
         if (debug() >= 2)
             debug_action_("move construct");
         other.object_ = 0;
     }
 
     GLObject & operator=(GLObject && other) noexcept
     {
         if (debug() >= 2)
             debug_action_("move assign");
         if (&other != this)
         {
             this->delete_objects(1, &object_);
             object_ = other.object_;
             other.object_ = 0;
         }
         return *this;
     }
 
     GLObject(GLObject const &) = delete;
     GLObject & operator=(GLObject const &) = delete;
 
     //// Object
 
     GLBASE_GET(GLuint, object)
 
     operator GLuint() const { return object(); }
 
     //// Name
 
     std::string name() const
     {
         return name_(object_type, object_);
     }
 
 protected:
 
     //// Debug
 
     void debug_action_(std::string const & action) const
     {
         return this->debug_action_(action, name());
     }
 
     //// Fail
 
     void fail_action_(std::string const & action) const
     {
         return this->fail_action_(action, name());
     }
 
 private:
 
     //// Object
 
     GLuint object_;
 
 };
 
 
 /// Guards
 
 #endif