具有模板成员功能的Pimpl Idiom [英] Pimpl Idiom with template member function

查看:119
本文介绍了具有模板成员功能的Pimpl Idiom的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用Pimpl Idiom,但是我遇到一个问题,成员函数之一是模板函数,因此必须在头文件中实现.

I want to use the Pimpl Idiom but I'm having a problem that one of the member functions is template function so it has to be implemented in a header file.

例如,下面的示例当然可以正常工作

For example this below works fine of course

//Foo.h
class Foo{
    struct Impl;
    Impl* ptr;
public:
    Foo();
    void bar(int);
    ~Foo();
};


//Foo.cpp
struct Foo::Impl{
    void bar(int i){ std::cout << "i = " << i << std::endl; }
};

Foo::Foo() : ptr{new Impl}{}
void Foo::bar(int i){ ptr->bar(i); }
Foo::~Foo(){ delete ptr; }

但是如果bar是模板函数,有什么方法可以实现类似的功能?

but is there any way to implement something similar if bar is a template function?

//Foo.h
class Foo{
    struct Impl;
    Impl* ptr;
public:
    Foo();
    template<typename T>
    void bar(T);
    ~Foo();
};

template<typename T>
void Foo::bar(T val)
{
    /*has to be implemented in a header but I cant call member function 
    on an incomplete type*/
    ptr->bar(val); //error
}

//Foo.cpp
struct Foo::Impl{
    template<typename T>
    void bar(T val){ std::cout << "val = " << val << std::endl; }
};
//...

编辑

在阅读了萨胡(R Sahu)的回答并看了所有其他评论之后,我发现自己做了建议的事情. .cpp文件中的显式模板实例化似乎是最清晰的选项,因此如果有人感兴趣,请参见以下代码.感谢所有回答!

After reading R Sahu's answer and by the looks of all the other comments I figured to do something like it was suggested to me. Explicit template instantiation in a .cpp file seemed like the most clearest option so here is the code if anyone is interested. Thanks to everyone who answered!

//Foo.h
class Foo{
    struct Impl;
    Impl* ptr;
public:
    Foo();
    template<typename T>
    void bar(T);
    ~Foo();
};


//Foo.cpp
struct Foo::Impl{
    template<typename T>
    void bar(T val){ std::cout << "val = " << val << std::endl; }
};

template<typename T>
void Foo::bar(T val)
{
    ptr->bar(val);
}

Foo::Foo() : ptr{ new Impl}{}
Foo::~Foo(){ delete ptr; }

#define instantiate_template_function(type)\
    template void Foo::bar(type);

instantiate_template_function(int)
instantiate_template_function(double)
instantiate_template_function(char)
instantiate_template_function(float)
instantiate_template_function(long long)

推荐答案

您可以实现

template<typename T>
void bar(T);

仅当T限于一组已知类型时,

作为成员函数.在这种情况下,您可以使用一组private成员函数,这些成员函数使用标签struct重载.

as a member function only if T is limited to a set of known types. In that case, you can use a set of private member functions that are overloaded using a tag struct.

class Foo
{
   template <typename T> struct Tag {};

   public:
      Foo();
      template<typename T>
         void bar(T val)
         {
            bar(val, Tag<T>{});
         }
      ~Foo();

   private:
      struct Impl;
      Impl* ptr;

      void bar(int val, Tag<int> tag);
      void bar(double val, Tag<double> tag);
      // etc.
      // Implement them in the .cpp file.
};

鉴于成员函数模板只能用于一组已知类型,您最好对其进行重载.

Given that the member function template can only be good for a known set of types, you might as well overload them.

class Foo
{
   public:
      Foo();

      void bar(int val);
      void bar(double val);
      // etc.

      ~Foo();

   private:
      struct Impl;
      Impl* ptr;    
};

这篇关于具有模板成员功能的Pimpl Idiom的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆