如何将提供模板化函数的依赖注入模板类卸载到pimpl类



我有一个应用程序类,它可以接受一个依赖类作为构造函数的模板参数。这个依赖类是提供应用程序类可以调用的某些模板化函数所必需的。我想把这个依赖类对象卸载到一个pimpl类中,这样应用程序类就不是一个模板类,因此只是头。

以下是我的大致意思。

///////////
// impl.h
///////////
template<typename Helper>
struct Impl
{
public:
Impl(Helper& helper) : helper_(helper)
{
}
template <typename T>
void someHelperFn1(T t)
{
helper_->fn1(t);
}

template <typename U>
SomeOtherClass<U> someHelperFn2()
{
return helper_->fn2();
}

private:
Helper& helper_;
};
///////////
// app.h
///////////
#include "impl.h"
class App
{
public:
template<typename Helper>
App(Helper &h) :impl_(new Impl) {}
template <typename T>
void someHelperFn1(T t)
{
impl_->someHelperFn1(t);
}

template <typename U>
SomeOtherClass<U> someHelperFn2()
{
return impl_->someHelperFn2();
}
void someAppFn();
private;
std::unique_ptr<Impl> impl_;
};
///////////
// app.cpp
///////////
void App::someAppFn()
{
// some useful code
}

我意识到上面的代码没有编译,因为Impl实际上是一个模板类,所以App也应该是一个模版类。这就是我想避免的,这样App就不是一个只有头的类。我发现了一些类似的东西,除了我想从helper依赖项调用的函数是模板函数,在这种情况下它们不是。除此之外,它似乎非常接近我想要做的事情。

关于如何避免将应用程序作为模板类,有什么想法吗?

我试着让helper类使用一个公共基类,但这在模板函数中是不可能的。

另外,请注意,我的编译器仅限于C++17。

您需要确保公共头文件(具有pimpl指针的类的头文件(不会公开实现的仅头文件的类模板。使用这样的接口。我没有依赖注入实现,因为这不应该是必需的。

#include <memory>
#include <iostream>
// public header file
// for pimpl pattern I often use an interface
// (also useful for unit testing later)
class PublicItf
{
public:
virtual void do_something() = 0;
virtual ~PublicItf() = default;
protected:
PublicItf() = default;
};
// the public class implements this interface
// and the pimpl pointer points to the same interface
// added advantage you will have compile time checking that
// the impl class will all the methods too.
class PublicClass final : 
public PublicItf
{
public:
PublicClass();
virtual ~PublicClass() = default;
void do_something() override;
private:
std::unique_ptr<PublicItf> m_pimpl; // the interface decouples from the template implementation (header file only) 
};
// private header file
// this can now be a template
template<typename type_t>
class ImplClass final :
public PublicItf
{
public:
void do_something() override
{
m_value++;
std::cout << m_value << "n";
}

private:
type_t m_value{};
};
// C++ file for Public class
// inlcude public header and impl header (template)
PublicClass::PublicClass() :
m_pimpl{ std::make_unique<ImplClass<int>>() }
{
};
void PublicClass::do_something()
{
m_pimpl->do_something();
}
// main C++ file
int main()
{
PublicClass obj;
obj.do_something();
return 0;
}

最新更新