我们有一个大量使用模板的头文件代码库,客户想要访问该代码库。例如,假设它在头文件
现在我们希望客户端尝试一组缩减的功能,而不需要暴露核心代码或重写整个代码库。一个想法是使用 PIMPL 惯用语法来包装这个核心代码。具体来说,我们可以创建一个名为
这段代码按照我的期望工作:https://wandbox.org/permlink/gso7mbe0UEOOPG7j 然而,有一件小事情困扰着我。具体来说,这个实现需要额外的间接层级...我们必须定义
如果我们能够告诉编译器,“实际上
具体来说,我想的是使用
foo.hpp
中包含了Foo
类。#ifndef FOO_HEADER
#define FOO_HEADER
#include <iostream>
template <typename T>
struct Foo {
Foo(){
// Do a bunch of expensive initialization
}
void bar(T t){
std::cout << t;
}
// Members to initialize go here...
};
#endif /* FOO_HEADER */
现在我们希望客户端尝试一组缩减的功能,而不需要暴露核心代码或重写整个代码库。一个想法是使用 PIMPL 惯用语法来包装这个核心代码。具体来说,我们可以创建一个名为
FooWrapper
的类,并编写头文件 foo_wrapper.hpp
:#ifndef FOO_WRAPPER_HEADER
#define FOO_WRAPPER_HEADER
#include <memory>
struct FooWrapper {
FooWrapper();
~FooWrapper();
void bar(double t);
private:
struct Impl;
std::unique_ptr<Impl> impl;
};
#endif /* FOO_WRAPPER_HEADER */
实现 foo_wrapper.cpp
:
#include "foo.hpp"
#include "foo_wrapper.hpp"
struct FooWrapper::Impl {
Foo<double> genie;
};
void FooWrapper::bar(double t){
impl->genie.bar(t);
}
FooWrapper::FooWrapper() : impl(new Impl){
}
FooWrapper::~FooWrapper() = default;
这段代码按照我的期望工作:https://wandbox.org/permlink/gso7mbe0UEOOPG7j 然而,有一件小事情困扰着我。具体来说,这个实现需要额外的间接层级...我们必须定义
Impl
类来持有Foo
类的成员。因此,所有操作都需要以这种形式的间接方式进行:impl->genie.bar(t);
。如果我们能够告诉编译器,“实际上
Impl
就是Foo<double>
类”,那将更好,这样,我们可以改为使用impl->bar(t);
。具体来说,我想的是使用
typedef
或using
来实现这一点。类似于:using FooWrapper::Impl = Foo<double>;
但是这段代码无法编译。所以接下来是问题:
- 有没有一种好的方法可以摆脱这种间接性?
- 是否有更好的习惯用法?
我正在寻找一个C++11的解决方案,但C++14也可能适用。重要的是要记住,该解决方案不能使用foo_wrapper.hpp
中的头文件foo.hpp
。不知何故,我们必须将该代码编译成库并仅分发编译好的库和foo_wrapper
头文件。