gpt4 book ai didi

c++ - 依赖模板函数的 Pimpl 习语实现

转载 作者:太空狗 更新时间:2023-10-29 20:39:05 24 4
gpt4 key购买 nike

请考虑下面的代码。

模板参数是一个处理程序类,必须提供函数bar()

我正在使用 Pimpl 习惯用法来隐藏 Foo 的实现细节。在使用模板参数之前,构造函数定义在 foo.cpp 中,一切都很好。

///////////    
// foo.h
///////////

class Foo
{
public:
template <class Handler>
Foo(Handler& handler);

void someFunction();

private:
/** Private implementation details. */
struct Impl;
const std::unique_ptr<Impl> m_impl;
};

template <class Handler>
Foo::Foo(Handler& handler) : m_impl{new Impl{handler}}
{
}

///////////
// foo.cpp
///////////

#include "foo.h"

/** Encapsulates the private implementation details of Foo. */
struct Foo::Impl
{
public:
Impl(Handler& handler) : m_handler(handler)
{
}

void someOtherFunction()
{
m_handler->bar();
}

private:
Handler& m_handler;

friend class Foo;
};

void Foo::someFunction()
{
m_impl->someOtherFunction();
}

引入模板参数后,我不得不将构造函数放在 foo.h 中,这会导致以下编译器错误:

不完整类型“Foo::Impl”的分配

我理解我收到错误的原因,但我想不出解决它的办法,仍然使用 Pimpl 习惯用法。

有人能帮忙吗?

最佳答案

您可以使用或不使用虚函数来解决这个问题。第一个选项稍微简单一些:使用虚函数,或者用于 Handler

class HandlerBase { .... virtual void bar() = 0; ... };
class Foo { ... std::unique_ptr<HandlerBase> handler; ... };

或用于实现

class ImplBase { ... virtual void someFunction() = 0; }
class Foo { ... std::unique_ptr<ImplBase> m_impl; ... }
template<typename Handler> class Impl : public ImplBase { ... Handler& m_handler; ...};

我认为这些实现起来相对简单。您可以看到,在使用 HandlerBase 时,您甚至不需要 pimpl 习惯用法。

另一种选择是使用 The Impossibly Fast C++ Delegates方法:

class Foo
{
public:
template <class Handler>
explicit Foo(Handler& handler)
: handler(&handler) {
someFunctionInstance = someFunctionTemplate<Handler>;
}

void someFunction() {
someFunctionInstance(handler);
}

private:
typedef void (*SomeFunctionType)(void* handler);

void* handler;
SomeFunctionType someFunctionInstance;

template<typename Handler>
static void someFunctionTemplate(void* handler) {
static_cast<Handler*>(handler)->bar();
}
};

Foo 的类型仍然独立于 Handler。构造函数中的赋值创建了 someFunctionTemplate 的自定义实例,它能够调用实际的 Handler 类型。 SomeFunctionInstance 是 Handler 模板实例化的结果,但由于它是静态函数,因此其类型也独立于 Handler。

但是这个解决方案很棘手并且确实包含一个 reinterpret_cast,它仍然是完全类型安全的。

关于c++ - 依赖模板函数的 Pimpl 习语实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29103193/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com