1

最近我从 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
    }
};

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

基本上,我想要的只是创建几个函数,每个类型都有一个(我是模板的新手: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);
}

在这种情况下,正确的实现是什么?

4

1 回答 1

1

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

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 });
    }
    //...
};
于 2021-03-25T01:17:43.607 回答