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 });
}
//...
};
最近我正在从 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 });
}
//...
};