解决缺乏外部库的常量问题

时间:2017-09-14 09:22:33

标签: c++ compiler-errors const-correctness

我正在使用缺少const-correctness的外部C ++库。假设我正在使用以下类的对象:

// Library.h
namespace Library {

class Message {
 public:
    std::string getData() {
        return data_;
    }
 private:
    std::string data_;
};

}  // namespace Library

请注意,getData()会返回一个副本,因此对方法的调用不会更改Message对象,而应该是const。但是,供应商决定不这样做。 在我的代码方面,const-correctness很重要,Message将在如下的函数中使用:

// MyApplication.cpp

template<class T>
void handleMessage(const T& msg) {
    std::string content = msg.getData();
    // interprete and process content ...
}

有没有办法实现这个目标?换句话说,如何解决error: passing 'const Library::Message' as 'this' argument discards qualifiers错误而不更改handleMessage函数的签名?

2 个答案:

答案 0 :(得分:4)

您还可以使用包含可变成员变量的包装器,如:

#include <string>

class Message {
 public:
    std::string getData() {
        return data_;
    }
    Message(std::string data): data_{data} { }
 private:
    std::string data_;
};

class MessageWrapper {
 public:
    MessageWrapper(Message message): message{message} {}
    std::string getData() const {
        return message.getData();
    }
 private:
    mutable Message message;
};

template<class T>
void handleMessage(const T& msg) {
    std::string content = msg.getData();

}

int main() {
    MessageWrapper mw{{"abc"}};
    handleMessage(mw);
}

[live demo]

修改

要强制const正确,您可以保存一次从邮件中检索到的数据,例如:

#include <string>
#include <optional>

class Message {
 public:
    std::string getData() {
        return data_;
    }
    Message(std::string data): data_{data} { }
 private:
    std::string data_;
};

class MessageWrapper {
 public:
    MessageWrapper(Message message): message{message} {}
    std::string getData() const {
        return (data)?(*data):(*(data = message.getData()));
    }
 private:
    mutable Message message;
    mutable std::optional<std::string> data;
};

template<class T>
void handleMessage(const T& msg) {
    std::string content = msg.getData();

}

int main() {
    MessageWrapper mw{{"abc"}};
    handleMessage(mw);
}

[live demo]

答案 1 :(得分:3)

你基本上有两种选择。您可以使用const_cast

template<class T>
void handleMessage(const T& msg) {
    std::string content = const_cast<T&>(msg).getData();
    // interprete and process content ...
}

只要您确定getData确实不修改任何成员,这就没问题了。或者,如果你不介意一些开销,你可以复制:

template<class T>
void handleMessage(const T& msg) {
    T copy = msg;
    std::string content = copy.getData();
    // interprete and process content ...
}

...或作为第三个选项,如果您想隐藏呼叫站点中的const_cast,您可以将其包裹起来:

class MyMessage {
     Message msg;
public:
     std::string getData() const {
         return const_cast<Message>(msg).getData();
     }
};