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?
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 });
}
//...
};