我想使用Pimpl Idiom,但我遇到的问题是其中一个成员函数是模板函数,所以它必须在头文件中实现。
例如,下面这个当然可以正常工作
//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
是模板函数,有没有办法实现类似的东西?
//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文件中的显式模板实例化似乎是最清晰的选项,因此如果有人感兴趣,这里是代码。感谢所有回答的人!
//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)
答案 0 :(得分:1)
您可以实施
float
仅当template<typename T>
void bar(T);
仅限于一组已知类型时才作为成员函数。在这种情况下,您可以使用一组使用标记结构重载的T
成员函数。
private
鉴于成员函数模板只能用于已知的一组类型,您也可以重载它们。
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.
};