【问题标题】:How can I offload dependency injected template class providing templated functions to pimpl class如何将提供模板化函数的依赖注入模板类卸载到 pimpl 类
【发布时间】:2022-11-01 14:55:31
【问题描述】:

我有一个应用程序类,它可以将依赖类作为构造函数的模板参数。这个依赖类需要提供应用程序类可以调用的某些模板化函数。我想将此依赖类对象卸载到 pimpl 类,因此应用程序类不是模板类,因此仅是标头。

这是我的意思的粗略概念。

///////////
// impl.h
///////////

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 就不是一个只有标题的类。我发现了一些东西similar,除了我想从辅助依赖项调用的函数是模板函数,在这种情况下它们不是。这似乎与我想做的非常接近。

关于如何避免使 App 成为模板类的任何想法?

我尝试让帮助类使用一个通用的基类,但这对于模板函数来说是不可能的。

【问题讨论】:

    标签: c++ templates function-templates pimpl-idiom


    【解决方案1】:

    您需要确保公共头文件(具有 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 << "
    ";
        }
    
    
    
    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;
    }
    

    【讨论】:

      猜你喜欢
      • 2010-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-19
      • 1970-01-01
      • 2019-05-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多