H4nzzU
H4nzzU

Reputation: 13

OpenGL -- Explicit specialization in non-namespace scope -- Function templates

Recently I was learning OpenGL basics from YouTube and while I was working with VS C++ compiler, everything worked like a charm, but since I moved to Clang I get error "explicit specialization in non-namespace scope" from the code below:

class VertexBufferLayout{
private:
    std::vector<VertexBufferElement> m_Elements;
public:
    VertexBufferLayout(){}

    template< typename T >
    void Push(GLuint count){}

    template<>
    void Push<GLfloat>(GLuint count){
        m_Elements.push_back({ GL_FLOAT, count, GL_FALSE });
        //Rest of code
    }
};

*It's an incomplete piece of class definition but I wanted to make this code more clear.

Basically, all I want is to create few functions, one for every type (and I am a newbie to templates :D). I'm using Clion with MinGW64 Clang and C++20.

I know that VS C++ compiler added a not-standard feature to support this, and Clang uses only standard methods.

Can anyone please tell me the workaround?

EDIT 1:

Attempt to implement the first solution from Yakov Galka's answer. I guess these two [[nodiscard]] lines or m_Stride variable might mess something up. I get the error "multiple definition of ".

(complete code this time) I should've posted it that way from the beginning.

class VertexBufferLayout{
    std::vector<VertexBufferElement> m_Elements;
    GLuint m_Stride;
public:
    VertexBufferLayout(): m_Stride(0) {}

    [[nodiscard]] std::vector<VertexBufferElement> GetElements() const& { return m_Elements; };
    [[nodiscard]] inline GLuint GetStride() const { return m_Stride; }

    template< typename T >
    void Push(GLuint count){}
};

template<>
void VertexBufferLayout::Push<GLfloat>(GLuint count){
    m_Elements.push_back({ GL_FLOAT, count, GL_FALSE });
    m_Stride += count * VertexBufferElement::GetSizeOfType(GL_FLOAT);
}

What is the right implementation in this case?

Upvotes: 1

Views: 260

Answers (1)

Yakov Galka
Yakov Galka

Reputation: 72539

The error says that it wants you to provide the specialization at a namespace scope. This compiles:

class VertexBufferLayout{
    std::vector<VertexBufferElement> m_Elements;
public:
    VertexBufferLayout(){}

    template< typename T >
    void Push(GLuint count){}
};

template<>
void VertexBufferLayout::Push<GLfloat>(GLuint count){
    m_Elements.push_back({ GL_FLOAT, count, GL_FALSE });
}
//...

Alternatively, you can use regular overloading to avoid specialization:

class VertexBufferLayout{
    std::vector<VertexBufferElement> m_Elements;
public:
    VertexBufferLayout(){}

    template< typename T >
    void Push(GLuint count){ Push_(count, (T*)0); }

    void Push_(GLuint count, GLfloat*){
        m_Elements.push_back({ GL_FLOAT, count, GL_FALSE });
    }
    //...
};

Upvotes: 1

Related Questions