模板const /非const方法

时间:2017-08-23 14:35:48

标签: c++ c++11 templates code-duplication

假设我们有这样的代码:

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() constINIFile<>::process()中没有重复的所有逻辑,是否有一种简单的方法可以使# WEB 0.1 FROM ubuntu:14.04 RUN apt-get update \ && apt-get install -y \ default-jre \ x11vnc \ xdotool \ xsel \ xvfb \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN DISPLAY=:1.0 \ && export DISPLAY \ && mkdir /root/.vnc \ && x11vnc -storepasswd 1234 /root/.vnc/passwd \ && Xvfb :1 -screen 0 493x476x8 & \ x11vnc -display :1.0 -usepw -forever & ENTRYPOINT ["java"] CMD ["-jar", "/var/bin/program.jar"] 成为docker run \ --name program-jar \ -p 5090:5900 \ -v /var/bin/program-jar/:/var/bin/ \ -d program-jar:0.1 成员函数?

2 个答案:

答案 0 :(得分:3)

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

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的调用操作符标记为const,并且您尝试通过const引用或对象的const副本调用process,则会出现编译错误(与你的解决方案不同)。这是因为const的{​​{1}}重载被调用,它将process添加到传入的处理器中,然后处理器上的调用操作符失败。

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

如果回调也会使调用运算符重载,那么此实现将转发到正确的转发,但您没有将其指定为条件。唯一要注意的是,const永远不应该访问成员变量process_impl,因为该成员变量将始终是可变的,即即使它不应该调用也会起作用(例如你的解决方案)。我故意暗影试图阻止这一点。这不是那么漂亮,但作为一个实现细节,它并没有那么糟糕,它确实消除了重复。

答案 1 :(得分:0)

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

这是代码。

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

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;
};