围绕缺乏外部库的const-correct性工作

Work around lacking const-correctness of external library

本文关键字:const-correct 工作 外部      更新时间:2023-10-16

我正在使用缺乏const-correct度的外部C 库。假设我正在使用以下类的对象:

// Library.h
namespace Library {
class Message {
 public:
    std::string getData() {
        return data_;
    }
 private:
    std::string data_;
};
}  // namespace Library

请注意,getData()返回副本,因此对该方法的调用不会更改Message对象,应为const。但是,供应商认为不是。在我的代码方面,const-correct度很重要,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函数的签名?

您也可以使用具有可变成员变量的包装器,例如:

#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]

您基本上有两个选项。您可以使用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();
     }
};