OpenGL -- 非命名空间范围内的显式特化 -- 函数模板

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

最近我正在从 YouTube 学习 OpenGL 基础知识,当我使用 VS C++ 编译器时,一切都很顺利,但自从我转向 Clang 后,我从代码中收到错误“非命名空间范围内的显式专业化”下面:

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
    }
};

*这是一段不完整的 class 定义,但我想让这段代码更清晰。

基本上,我只想创建几个函数,每种函数一个(我是模板的新手 :D)。 我将 Clion 与 MinGW64 Clang 和 C++20 一起使用。

我知道 VS C++ 编译器添加了一个非标准功能来支持它, 并且 Clang 仅使用标准方法。

谁能告诉我解决方法?

编辑 1:

尝试实施 Yakov Galka 的回答中的第一个解决方案。 我想这两个 [[nodiscard]] 行或 m_Stride 变量可能会搞砸。我收到错误消息“多重定义”。

(这次是完整的代码)我应该从一开始就这样发布的。

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);
}

在这种情况下,正确的实施方式是什么?

错误表明它希望您在命名空间范围内提供专业化。这编译:

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

或者,您可以使用常规重载来避免特化:

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