首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何让C++编译器知道一个函数是“`Idempotent`”

如何让C++编译器知道一个函数是“`Idempotent`”
EN

Stack Overflow用户
提问于 2016-12-22 16:00:11
回答 2查看 183关注 0票数 1

我正在编写一个OpenGL C++包装器。这种包装的目的是减少复杂和易出错的使用。

例如,我目前希望用户只关注OpenGL Context。为此,我编写了一个类gl_texture_2d。众所周知,OpenGL texture基本上有以下操作:

  1. 将它的u/v参数设置为repeat/mirror
  2. 将其设置为min/mag filterlinear
  3. ..。

基于此,我们有:

代码语言:javascript
复制
class gl_texture_2d 
{
public:
  void mirror_u(); // set u parameter as mirror model
  void mirror_v(); // set v parameter as mirror model
  void linear_min_filter(); // ...
  void linear_mag_filter(); // ...
};

我们知道,只有当the handle of OpenGL texture object当前绑定到OpenGL context时,我们才能执行这些操作。假设我们有一个函数这样做: void (GLuint htex);//实际上是相关GL函数的别名

好的,我们现在可以将我们的gl_texture_2d用法设计为:

代码语言:javascript
复制
gl_texture_2d tex;
bind(tex.handle());
tex.mirror_u();
tex.linear_min_filter();
unbind(tex.handle());

它证实了GL的逻辑,但它失去了包装的重要性,对吗?作为一名用户,我希望操作如下:

代码语言:javascript
复制
gl_texture_2d tex;
tex.mirror_u();
tex.linear_min_filter();

为实现这一目标,我们必须实现以下功能:

代码语言:javascript
复制
void gl_texture_2d::mirror_u()
{
  glBindTexture(GL_TEXTURE_2D, handle());
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
  glBindTexture(GL_TEXTURE_2D, 0);
}

始终在内部执行绑定操作,确保操作是有效的。但是费用太贵了!

守则:

代码语言:javascript
复制
tex.mirror_u();
tex.mirror_v();

将扩展为一对无意义的绑定/取消绑定操作。

那么,是否有任何机制可以让编译器知道:

  1. 如果bind(b)紧跟bind(a),则可以删除bind(a)
  2. 如果在一个块中发生两次bind(a),则最后一个不起作用。
EN

回答 2

Stack Overflow用户

发布于 2016-12-22 16:33:33

如果您正在使用DSA前OpenGL,并且您绝对必须用您自己的API直接包装OpenGL调用,那么用户可能就必须知道整个绑定到编辑的事情了。毕竟,如果他们为呈现目的绑定了一个纹理,那么他们会尝试修改一个纹理,这可能会破坏当前的绑定。

因此,您应该将绑定到编辑的概念直接构建到API中。

也就是说,纹理对象( BTW,不应仅限于2D纹理)实际上不应该具有修改它的功能,因为如果不绑定OpenGL纹理(或者没有DSA,这是您真正应该学习的),您就不能修改它。它不应该有mirror_u等等;这些函数应该是绑定器对象的一部分:

代码语言:javascript
复制
bound_texture bind(some_texture, tex_unit);
bind.mirror_u();
...

bound_texture的构造函数将some_texture绑定到tex_unit。其成员函数将修改该纹理(注意:他们需要调用glActiveTexture以确保没有人更改活动纹理单元)。

bound_texture的析构函数应该自动解除纹理的绑定。但是您应该有一个手动解除绑定的release成员函数。

票数 1
EN

Stack Overflow用户

发布于 2016-12-22 16:06:54

您将无法在编译级别上这样做。相反,如果您真的担心这类错误的时间开销,经理对象可能是最好的选择:

代码语言:javascript
复制
class state_manager {
    GLuint current_texture;
    /*Maybe other stuff?*/
public:
    void bind_texture(gl_texture_2d const& tex) {
        if(tex.handle() != current_texture) {
            current_texture = tex.handle();
            glBindTexture(/*...*/, current_texture);
        }
    }
};

int main() {
    state_manager manager;
    /*...*/
    gl_texture_2d tex;
    manager.bind(tex);
    manager.bind(tex); //Won't execute the bind twice in a row!
    /*Do Stuff with tex bound*/

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41287151

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档