Loading

利用PImpl在C++14中优雅调用C++17方法

诉求

你的工程由C++14写成,某天你看中了一个功能强大的三方库,一切都好除了该库仅支持C++17编译,对于比较复杂的三方库使用C++14进行重构工作量太大,有没有优雅的办法?

实现

历史总是惊人的相似,为了解决这一问题前人发明了PImpl编程方法用于隐藏class的实现细节,头文件中仅声明抽象class通过一层wrapper完成api的转换。听不懂?上代码。

代码

假设我有一个库必须调用C++17的std::byte作为入参。

class checker:
{
public:
    checker(std::byte b): b_{b} {};
    void show()
    {
        std::cout << std::bitset<8>(std::to_integer<int>(b)) << std::endl;
    }
private:
    std::byte b_;
};

显然C++14无法正常编译,此时引入PImpl方法。
分别定义checker_wrapper.hpp

// checker_wrapper.hpp
#pragma once
#include <memory>

class CheckerWrapper
{
public:
    CheckerWrapper(uint8_t b);
    ~CheckerWrapper(); // must, see ref.3
    void show();
private:
    class impl;
    std::unique_ptr<impl> pimpl_;
};

以及checker_wrapper.cpp文件:

// checker_wrapper.cpp
#include "checker_wrapper.hpp"
#include <iostream>
#include <cstddef>
#include <bitset>

class CheckerWrapper::impl
{
public:
    impl(std::byte b): b_{b} {};
    void show()
    {
        std::cout << std::bitset<8>(std::to_integer<int>(b_)) << std::endl;
    }
private:
    std::byte b_;
};

CheckerWrapper::CheckerWrapper(uint8_t b): pimpl_{std::make_unique<impl>(std::byte{b})} {}
CheckerWrapper::~CheckerWrapper() = default;
void CheckerWrapper::show()
{
    pimpl_->show();
}

假设调用工程为test.cpp

#include "checker_wrapper.hpp"

int main()
{
    CheckerWrapper checker{42};
    checker.show();
    return 0;
}

随后将checker_wrapper编译为静态库,配合C++14风格的头文件checker_wrapper.hpp调用既可。

g++ -std=c++17 -c checker_wrapper.cpp
ar rvs libchecker.a checker_wrapper.o
g++ -std=c++14 test.cpp libchecker.a

参考

PImpl - cppreference.com
c++ - How to create a static library with g++? - Stack Overflow
EffectiveModernCppChinese/item22.md at master · CnTransGroup/EffectiveModernCppChinese · GitHub

posted @ 2023-06-05 16:07  azureology  阅读(216)  评论(0)    收藏  举报