I need to overload assignement in one of my opengl based classes : problem is that this case is not so simple, because it uses Opengl "objects" : so copying class attributes is not enough. So what would be the correct way to overload the =, and copy constructor methods ? Here is my code :
Shader.h :
#pragma once
#include <GL/glew.h>
#include <map>
#include <string>
#include "alpha/LogManager.h"
#include "alpha/Component.h"
#include "alpha/Exceptions.h"
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#define NUM_SHADER_TYPES 3
#define NO_UNIFORM -1
class Shader : public Component
{
public:
    Shader();
    virtual ~Shader();
    void loadFromText(GLenum type, const std::string& src);
    void loadFromFile(GLenum type, const char* fileName);
    void loadFromPreCompiledText(GLenum type, const std::string& src){}
    void loadFromPreCompiledFile(GLenum type, const char* fileName){}
    void CreateAndLink();
    GLuint GetObject() const;
    ///accesses elements : shaders/uniforms;
    GLuint GetAttribLocation(const char* attrib);
    GLuint GetUniformLocation(const char* unif);
    void UpdateUniformMatrix4f(const char* unif, const glm::mat4& val, GLboolean inverse = false);
    void UpdateUniformMatrix3f(const char* unif, const glm::mat3& val, GLboolean inverse = false);
    void UpdateUniformMatrix2f(const char* unif, const glm::mat2& val, GLboolean inverse = false);
    void Bind() const override;
    void UnBind() const override;
    void Dispose() override;
    ///MEMBER FUNCTION GENERATORS
    #define __ALPHA_SHADER_PROGRAM_UNIFORM_DECLERATION(OGL_TYPE, TYPE_SUFFIX)\
        void UpdateUniform1##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0); \
        void UpdateUniform2##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0, OGL_TYPE v1); \
        void UpdateUniform3##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0, OGL_TYPE v1, OGL_TYPE v2); \
        void UpdateUniform4##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0, OGL_TYPE v1, OGL_TYPE v2, OGL_TYPE v3); \
        void UpdateUniform1##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count = 1);\
        void UpdateUniform2##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count = 1);\
        void UpdateUniform3##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count = 1);\
        void UpdateUniform4##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count = 1);
    ///Implement Methods
    __ALPHA_SHADER_PROGRAM_UNIFORM_DECLERATION(GLfloat, f);
    __ALPHA_SHADER_PROGRAM_UNIFORM_DECLERATION(GLdouble, d);
    __ALPHA_SHADER_PROGRAM_UNIFORM_DECLERATION(GLint, i);
    __ALPHA_SHADER_PROGRAM_UNIFORM_DECLERATION(GLuint, ui);
    ///undef macro
    #undef __ALPHA_SHADER_PROGRAM_UNIFORM_DECLERATION(OGL_TYPE, TYPE_SUFFIX)
    Shader& operator=(const Shader& other) = delete;
    Shader(const Shader& shader) = delete;
private:
    enum ShaderType{
        VERTEX_SHADER,
        FRAGMENT_SHADER,
        GEOMETRY_SHADER
    };
    int m_numShaders;
    GLuint m_object;
    bool _hasCreated;
    bool _hasDisposed;
    GLuint _shaders[NUM_SHADER_TYPES]; /// VERTEX, FRAGMENT, GEOMETRY
    std::map<std::string, GLuint> _attribList;
    std::map<std::string, GLuint> _unifLocationList;
    std::map<std::string, bool> _registeredUnifs;
};
Shader.cpp
#include "alpha/Shader.h"
#include "alpha/LogManager.h"
#include <fstream>
#include <assert.h>
#define GL_NULL 0
Shader::Shader()
    : m_numShaders(0), m_object(0), _hasCreated(false), _hasDisposed(false)
{
    _shaders[VERTEX_SHADER] = 0;
    _shaders[FRAGMENT_SHADER] = 0;
    _shaders[GEOMETRY_SHADER] = 0;
    _attribList.clear();
    _unifLocationList.clear();
}
Shader::~Shader(){
    Dispose();
}
void Shader::loadFromText(GLenum type, const std::string& text){
    try
    {
        switch (type)
        {
            case GL_VERTEX_SHADER:
                if(glIsShader(_shaders[VERTEX_SHADER]) == GL_TRUE)
                    throw TypeRegisteredTwiceException();
                break;
            case GL_FRAGMENT_SHADER:
                if(glIsShader(_shaders[FRAGMENT_SHADER]) == GL_TRUE)
                    throw TypeRegisteredTwiceException();
                break;
            case GL_GEOMETRY_SHADER:
                if(glIsShader(_shaders[GEOMETRY_SHADER]) == GL_TRUE  )
                    throw TypeRegisteredTwiceException();
                break;
            default:
                throw UnknownTypeException();
                break;
        }
        GLuint shader = glCreateShader(type);
        const char* cstr = text.c_str();
        glShaderSource(shader, 1, &cstr, nullptr);
        ///compile + check shader load status
        GLint status;
        glCompileShader(shader);
        glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
        if(status == GL_FALSE){
            GLint infoLogSize;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogSize);
            GLchar *infoLog = new GLchar[infoLogSize];
            glGetShaderInfoLog(shader, infoLogSize, nullptr, infoLog);
            LOG_ERROR("Shader", infoLog);
            delete [] infoLog; /// no throw between new and delete !
        }
        if(m_numShaders >= 4)
        {
            throw OutOfBoundsExcpetion();
        }
        _shaders[m_numShaders++]=shader;
    }
    catch(std::exception & e){
        LOG_ERROR_INFO("AN ERROR OCCURED", "\n", e.what() );
        LOG_ERROR("Shader", "IGNORING ADDED SHADER !");
    }
}
void Shader::CreateAndLink(){
    try{
        if(glIsProgram(m_object) == GL_TRUE)
            throw CreatedTwiceException();
        m_object = glCreateProgram();
        ///OK CREATED PROGRAM !
        _hasCreated = true;
        if(_shaders[VERTEX_SHADER] != 0)
            glAttachShader(m_object, _shaders[VERTEX_SHADER]);
        else
            throw NotLoadedException();
        if(_shaders[FRAGMENT_SHADER] != 0)
            glAttachShader(m_object, _shaders[FRAGMENT_SHADER]);
        else
            throw NotLoadedException();
        if(_shaders[GEOMETRY_SHADER] != 0)
            glAttachShader(m_object, _shaders[GEOMETRY_SHADER]);/// OK, not compulsary...
        ///link + check
        GLint status;
        glLinkProgram(m_object);
        glGetProgramiv(m_object, GL_LINK_STATUS, &status);
        if(status == GL_FALSE){
            GLint infoLogSize;
            glGetProgramiv(m_object, GL_INFO_LOG_LENGTH, &infoLogSize);
            GLchar *infoLog = new GLchar[infoLogSize];
            glGetProgramInfoLog(m_object, infoLogSize, nullptr, infoLog);
            delete [] infoLog;
        }
        std::cout << "Shader created : ID = " << m_object << std::endl;
        glDetachShader(m_object, _shaders[VERTEX_SHADER]);
        glDetachShader(m_object, _shaders[FRAGMENT_SHADER]);
        glDetachShader(m_object, _shaders[GEOMETRY_SHADER]);
        glDeleteShader(_shaders[VERTEX_SHADER]);
        glDeleteShader(_shaders[FRAGMENT_SHADER]);
        glDeleteShader(_shaders[GEOMETRY_SHADER]);
    }
    catch(std::exception & e){
         LOG_ERROR_INFO("Shader", "AN ERROR OCCURED\n", e.what() );
         EXIT(1);
    }
}
void Shader::Bind() const{
    glUseProgram(m_object);
}
void Shader::UnBind() const{
    glUseProgram(GL_NULL);
}
GLuint Shader::GetAttribLocation(const char* attrib){
    auto it = _attribList.find(attrib);
    if(it == _attribList.end())
    {
        GLuint loc = glGetAttribLocation(m_object, attrib);
        if(loc == (unsigned)-1)
        {
            LOG_INFO("Shader Warning : Attrib", attrib, "is inactive !");
        }
        it = _attribList.insert({attrib, loc}).first;
    }
    return it->second;
}
GLuint Shader::GetUniformLocation(const char* unif){
    auto it = _unifLocationList.find(unif);
    if(it == _unifLocationList.end())
    {
        GLuint loc = glGetUniformLocation(m_object, unif);
        if(loc == (unsigned)-1)
        {
            LOG_INFO("Shader Warning : Uniform", unif, "is inactive !");
        }
        it = _unifLocationList.insert({unif, loc}).first;
    }
    return it->second;
}
GLuint Shader::GetObject() const{ return m_object; }
void Shader::UpdateUniformMatrix4f(const char* unif, const glm::mat4& val, GLboolean inverse){
    glUniformMatrix4fv(this->GetUniformLocation(unif), 1, inverse, glm::value_ptr(val));
}
void Shader::UpdateUniformMatrix3f(const char* unif, const glm::mat3& val, GLboolean inverse){
    glUniformMatrix3fv(this->GetUniformLocation(unif), 1, inverse, glm::value_ptr(val));
}
void Shader::UpdateUniformMatrix2f(const char* unif, const glm::mat2& val, GLboolean inverse){
    glUniformMatrix2fv(this->GetUniformLocation(unif), 1, inverse, glm::value_ptr(val));
}
#define __ALPHA_SHADER_PROGRAM_UNIFORM_IMPLEMENTATION(OGL_TYPE, TYPE_SUFFIX)\
    void Shader::UpdateUniform1##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0)\
    { glUniform1 ## TYPE_SUFFIX (this->GetUniformLocation(name), v0); }\
\
    void Shader::UpdateUniform2##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0, OGL_TYPE v1)\
    { glUniform2 ## TYPE_SUFFIX (this->GetUniformLocation(name), v0, v1); }\
\
    void Shader::UpdateUniform3##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0, OGL_TYPE v1, OGL_TYPE v2)\
    { glUniform3 ## TYPE_SUFFIX (this->GetUniformLocation(name), v0, v1, v2); }\
\
    void Shader::UpdateUniform4##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0, OGL_TYPE v1, OGL_TYPE v2, OGL_TYPE v3)\
    { glUniform4 ## TYPE_SUFFIX (this->GetUniformLocation(name), v0, v1, v2, v3); }\
\
    void Shader::UpdateUniform1##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count) /** sizei=1 by default */\
    { glUniform1 ## TYPE_SUFFIX ## v (this->GetUniformLocation(name), count, v); }\
\
    void Shader::UpdateUniform2##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count) /** sizei=1 by default */\
    { glUniform2 ## TYPE_SUFFIX ## v (this->GetUniformLocation(name), count, v); }\
\
    void Shader::UpdateUniform3##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count) /** sizei=1 by default */\
    { glUniform3 ## TYPE_SUFFIX ## v (this->GetUniformLocation(name), count, v); }\
\
    void Shader::UpdateUniform4##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count) /** sizei=1 by default */\
    { glUniform4 ## TYPE_SUFFIX ## v (this->GetUniformLocation(name), count, v); }\
__ALPHA_SHADER_PROGRAM_UNIFORM_IMPLEMENTATION(GLfloat, f);
__ALPHA_SHADER_PROGRAM_UNIFORM_IMPLEMENTATION(GLdouble, d);
__ALPHA_SHADER_PROGRAM_UNIFORM_IMPLEMENTATION(GLint, i);
__ALPHA_SHADER_PROGRAM_UNIFORM_IMPLEMENTATION(GLuint, ui);
///undef macro
#undef __ALPHA_SHADER_PROGRAM_UNIFORM_IMPLEMENTATION()
void Shader::loadFromFile(GLenum which, const char* fileName){
    std::ifstream fparser;
    fparser.open(fileName, std::ios_base::in);
    if(fparser){
        ///read + load
        std::string buffer(std::istreambuf_iterator<char>(fparser), (std::istreambuf_iterator<char>()));
        loadFromText(which, buffer);
    }
    else{
        LOG_ERROR_INFO("Shader", "Invalid fileName path", fileName);
    }
}
void Shader::Dispose(){
    if(!_hasDisposed)
    {
        glDeleteProgram(m_object);
        std::cout << "Disposed Shader object : ID was " <<  m_object << std::endl;
        m_object = -1;
        _hasDisposed = true;///no more calls of Dispose() !
    }
}
Edit : I ended up adding a move constructor as you suggested :
Shader::Shader(Shader&& other){
    this->m_object = other.m_object;
    other.m_object = 0;
    this->m_numShaders = other.m_numShaders;
    this->_hasCreated = other._hasCreated;
    this->_hasDisposed = other._hasDisposed;
    for(unsigned i = 0; i < NUM_SHADER_TYPES; ++i)
    {
        this->_shaders[i] = other._shaders[i];
        other._shaders[i] = 0;
    }
    this->_attribList = std::move(other._attribList);
    this->_unifLocationList = std::move(other._unifLocationList);
    this->_unifLocationList = std::move(other._unifLocationList);
}
Thanks for helping :)
 
    