У меня очень неприятная ситуация, когда я пытаюсь отделить свое программное обеспечение от зависимости времени компиляции от предоставляемого поставщиком API. Типичный способ сделать это - реализовать класс «обертка» вокруг API, который использует идиому PIMPL, чтобы скрыть предоставляемый поставщиком API полностью за непрозрачным указателем.
Например ...
wrapper.h:
#pragma once
#include <memory>
class Wrapper {
public:
Wrapper();
~Wrapper();
// Function that uses vendor API in its implementation
void Function1();
private:
struct Impl;
std::unique_ptr<Impl> m_impl;
};
wrapper.cpp
#include "wrapper.h"
#include <memory>
#include <vendor/api.h>
struct Wrapper::Impl {
void Function1() {
// Vendor API call hidden entirely within the private implementation
VendorApiFunction1();
}
};
Wrapper::Wrapper() : m_impl(std::make_unique<Impl>()) {}
Wrapper::~Wrapper() = default;
// Forward call to the private implementation
Wrapper::Function1() {
m_impl->Function1();
}
Проблема заключается в том, что предоставляемый поставщиком API-интерфейс определяет некоторые глобальные typedef
, которые он использует в своем интерфейсе. Что делает объявление Function1()
в wrapper.h
похожим на это:
void Function1(CUSTOM_API_TYPE input);
Затем эти входные данные передаются в реализацию, где в конечном итоге передаются функции API, предоставляемой поставщиком.
Это создает очень неприятную проблему ... Так как typedef
s не может быть объявлено вперед, теперь я вынужден добавить #include <vendor/api.h>
к вершине wrapper.h
, чтобы сделать CUSTOM_API_TYPE
доступным. Добавление заголовка вендора к wrapper.h
затем накладывает зависимость времени компиляции от API, предоставленного вендором, для всех клиентов wrapper.h
, и это именно то, что я использовал для обозначения PIMPL, чтобы избежать ...
Есть ли какой-нибудь стандартный способ справиться с такой ситуацией?