我對這段代碼的目標是將函式引數的傳遞值限制為選擇的幾個可能性,在 C 20 的編譯時進行檢查。我最初失敗的第一次嘗試看起來像這樣:
template<GLenum shader_type>
requires requires
{
shader_type == GL_VERTEX_SHADER ||
shader_type == GL_FRAGMENT_SHADER ||
shader_type == GL_COMPUTE_SHADER;
}
GLuint create_shader(std::filesystem::path const& shader_path, GLenum shader_type)
這是行不通的,我不會與編譯器爭論,但我將它包含在此處以幫助說明我的宣告目標。我的規格:
- 將單個傳遞
GLenum給一組當前支持的三種型別。最好以特別的方式,例如不需要太多樣板。 - 對于用戶,可以像這樣呼叫這個函式:
create_shader("my/path", GL_FRAGMENT_SHADER). 看不到模板。
這段代碼的主要問題是:
declaration of 'shader_type' shadows a template parameter. 我可以看到這是因為GLenum shader_type模板引數和函式引數中的規范,但我希望編譯器可能會以某種方式從函式 args 推斷型別。shader_type == GL_VERTEX_SHADER || shader_type == GL_FRAGMENT_SHADER || shader_type == GL_COMPUTE_SHADER根本沒有做它的作業。我可以GL_GEOMETRY_SHADER在沒有編譯時問題的情況下通過。(我希望我可以對運行時說同樣的話)
看了這個問題后,我想出了下一個:
template<GLenum shader_type>
requires requires
{
requires shader_type == GL_VERTEX_SHADER ||
shader_type == GL_FRAGMENT_SHADER ||
shader_type == GL_COMPUTE_SHADER;
}
GLuint create_shader(std::filesystem::path const& shader_path)
在將傳遞的值限制為這些值時,這似乎可以正常作業,但是,它確實需要shader_type作為模板引數傳入。這真的很好,但它讓我想到了我的問題:
- Is there a way to do as I've done in terms of constraints but without having the user pass in
shader_typeas a template parameter explicitly, instead preferring a function argument? - Is there a way of writing this declaration with fewer
requires? I suspect not, but it would be nice if I can cut one out. - Generally, does anyone know any alternatives which are "better" on the whole. Perhaps referring to my spec at the top of this question for what "better" might be.
Appendix:
- I'm aware of
constexprand that I could probably do the check inside the function, but doing it through constraints and concepts is also a bit of exploration for me, as a learner. - In case people are confused by
GLenumor any of the other non-standard code:
typedef unsigned int GLenum;
typedef unsigned int GLuint;
#define GL_FRAGMENT_SHADER 0x8B30
#define GL_VERTEX_SHADER 0x8B31
#define GL_COMPUTE_SHADER 0x91B9
uj5u.com熱心網友回復:
如果你想約束一個模板引數,一個requires就足夠了:
template <GLenum shader_type>
requires(shader_type == GL_VERTEX_SHADER || shader_type == GL_FRAGMENT_SHADER)
void foo() {}
函式引數可以像這樣被約束,代價是要求它是一個編譯時常量:
struct ShaderType
{
GLenum value;
consteval ShaderType(GLenum value) : value(value)
{
if (shader_type != GL_VERTEX_SHADER && shader_type != GL_FRAGMENT_SHADER)
throw "Invalid value!";
// Normally it's not a good idea to throw pointers,
// but here it just used to stop the compilation.
}
};
void foo(ShaderType type) {}
uj5u.com熱心網友回復:
您不能使用編譯時構造(如requires子句)來約束運行時值(如函式引數)。您想要的不是編譯時約束;這是一個運行時合約。
C 還沒有這樣的特性。目前您能做的最好的事情是使用static constexpr僅允許某些值的正確列舉(或型別化變數)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/433975.html
標籤:c templates interface c 20 c -概念
下一篇:使用lldb除錯時重寫模板名稱
