首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模板const /非const方法

模板const /非const方法
EN

Stack Overflow用户
提问于 2017-08-23 14:35:47
回答 2查看 921关注 0票数 4

假设我们有这样的代码:

代码语言:javascript
复制
template<class CALLBACK>
struct INIFile{
    INIFile(CALLBACK &processor) :
                    processor(processor     ){}

    bool process(){
        // lots of code here,
        // call processor
        processor(123);

        return true;
    }

    CALLBACK    &processor;
};


struct MyProcessor{
    void operator()(int val){
        // do something
    }
};

struct MyConstProcessor{
    void operator()(int val) const{ // !!!!!
        // do something
    }
};

int main(){
    MyProcessor p;
    INIFile<MyProcessor> ini(p);
    ini.process();

    // const case:
    MyConstProcessor cp;
    INIFile<MyConstProcessor> cini(cp);
    cini.process();
}

在这两种情况下,INIFile<>::process()都是一个非const成员函数。

如果process()const,那么有什么简单的方法可以使CALLBACK::operator()成为const成员函数,而不重复INIFile<>::process()中的所有逻辑?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-08-23 22:30:10

通过执行以下操作解决了您的问题:

代码语言:javascript
复制
template<class CALLBACK>
struct INIFile{
    INIFile(CALLBACK &processor) :
                    processor(processor){}

    template <class T>
    bool process_impl(T& processor) const {
        // deliberately shadow processor
        // reduce likelihood of using member processor, but can use other member variables

        // lots of code
        processor(123);
        return true;
    }

    bool process() const {
        return process_impl(const_cast<const CALLBACK&>(processor));
    }
    bool process() {
        return process_impl(processor);
    }

    CALLBACK&    processor;
};

当然,这在技术上重载了process,但是它具有与您想要的完全相同的效果。如果processor的call运算符没有被标记为const,并且您试图通过对象的const引用或const副本调用process,则会得到一个编译错误(与您的解决方案不同)。这是因为调用了processconst过载,它将const添加到传递的处理器中,然后处理器上的调用操作符当然会失败。

但是,如果回调确实提供了一个const调用操作符,那么任何一个进程调用都将执行完全相同的操作。这实际上意味着您可以在INIFile的const副本上调用INIFile,这相当于processconst

如果回调也重载了调用操作符,则此实现将转发到正确的位置,但您没有将其指定为条件。唯一要注意的是,process_impl永远不应该访问成员变量processor,因为该成员变量总是可变的,也就是说,即使调用不应该(就像在解决方案中那样),调用也会工作。我故意暗影来阻止这件事。这并不是很漂亮,但作为实现细节,它并不是那么糟糕,它确实消除了重复。

票数 3
EN

Stack Overflow用户

发布于 2017-08-23 21:44:12

我发现的另一种方式,但我不太喜欢它是使用指针,而不是引用。

这是密码。

注意,在这种特殊情况下,我们根本不需要检查nullptr

代码语言:javascript
复制
template<class CALLBACK>
struct INIFile{
    INIFile(CALLBACK &processor) :
                    processor(& processor ){}

    bool process() const{
        // lots of code here,
        // call processor
        processor->operator()(123);

        return true;
    }

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

https://stackoverflow.com/questions/45842717

复制
相关文章

相似问题

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