如何将 pimpl 成语与模板化函数一起使用

How to use pimpl idiom with templated functions

提问人:Tharani B 提问时间:1/24/2023 更新时间:1/24/2023 访问量:123

问:

我有一个具有模板成员函数的类,私有成员需要通过 pimpl idiom 方法放入实现类中。

Foo.hpp的

#include <iostream>
class Foo
{
public:
private:
    class FooImpl;
    std::unique_ptr<FooImpl> impl_;

public:
    Foo() = default;
    template <class F, class... Args>
    auto SomeFunction ( F &&f, Args &&...args) -> boost::unique_future<decltype (f(args...))>;
};

Foo.cpp

#include <Foo.hpp>
#include <FooImpl.hpp>
template <class... Args>
template <class F, class... Args>
auto SomeFunction ( F &&f, Args &&...args) -> boost::unique_future<decltype (f(args...))>
{
   impl->SomeFunction(std::forward<F>(f),std::forward<Args>(args)...);
}

FooImpl.hpp

#include <Foo.hpp>
class Foo::FooImpl
{
public:
    FooImpl() = default;
    template <class F, class... Args>
    auto SomeFunction ( F &&f, Args &&...args) -> boost::unique_future<decltype (f(args...))>;
private:
    int dummy;
};

FooImpl.cpp

#include <FooImpl.hpp>
template <class... Args>
template <class F, class... Args>
auto SomeFunction ( F &&f, Args &&...args) -> boost::unique_future<decltype (f(args...))>
{
   //Do Something...
}

我尝试了以下方法,但在我的情况下没有任何效果:-

  1. 具有虚拟功能。这不起作用,因为虚拟函数无法模板化。
  2. 显式实例化所有模板实例,例如
template class Foo<int>;
template class Foo<float>;

这不适合我的情况,因为任何类型都可以出现在我的函数中。我无法显式实例化所有类型。

还有其他方法吗?是否可以使用模板函数实现 pimpl 成语?或者除了疙瘩成语之外还有其他选择吗?

C++ 模板 C++17 variadic-templates pimpl-idiom

评论

4赞 Davis Herring 1/24/2023
这难道不是本质上不可能的吗?您希望避免在实现更改时重新编译客户端,但只有这些客户端知道要应用此类成员函数的类型(模板专用化)。
0赞 sklott 1/24/2023
对于您的特定情况,您可能可以在 中执行“回调”并从 中调用它。FooFooImpl
0赞 Homer512 1/24/2023
一种方法是使用类型擦除:使用由模板构成的公共接口,并将其与使用虚拟方法、函数指针和 void 指针的私有实现相结合。模板化的前端可以使用类似的东西,以后端可以处理的统一方式包装参数std::anystd::function
0赞 stefaanv 1/24/2023
这不是一个答案,因为我已经很久没有使用 pimpls,但除了看起来不对之外,这难道不能通过将私有模板函数放在 Foo.cpp 而不是 FooImpl.cpp 中来解决吗,因为重点是模板函数需要与调用者位于同一翻译单元中,唯一的调用者应该是类 Foo。有一个记录在案的部分,说明这是为了克服 C++ 的限制。如果我错了,请纠正我,因为我现在需要太多时间来验证它。

答: 暂无答案