在模板特化中避免构造函数重复
avoid constructor duplication in template specialization
本文关键字:构造函数 更新时间:2023-10-16
假设我有一个基类,它存储对某个class Bar
的引用:
class FooBase
{
public:
FooBase( Bar &ctx ) : _barCtx( ctx ) {};
virtual ~FooBase() {};
// Some other functions
protected:
Bar &_barCtx;
};
我想做的是在此基础上添加一个继承级别,其中class Foo<T>
将添加一些功能。
template< typename T >
class Foo : public FooBase
{
public:
Foo( Bar &ctx ) : FooBase( ctx ) {};
bool doSomething( int a );
};
然后,Foo<T>
的一些实例需要提供doSomething()
的不同版本,因此使用模板专门化。问题是,在Foo<>
的每个专门化版本中,我必须重新实现构造函数并将Bar
的引用传递给超类。这基本上是复制和粘贴代码,我想避免。
class Baz;
template<>
class Foo<Baz> : public FooBase
{
public:
Foob( Bar &ctx ) : FooBase( ctx ) {};
bool doSomething( std::string &str, int x, float g );
};
本练习的重点是提供具有不同签名的不同类型的doSomething()
。那么,如果不使用c++ 11(因为我被困在GCC 4.6.3上),有没有一种方法可以避免这种代码重复?或者,是否有更好的方式提供不同的doSomething()
?
我实际上认为SFINAE方法更好,但如果由于某种原因它不适合您,那么专门化类模板的单个成员函数可能适合您。但是,您必须在泛型模板中声明所有重载,然后提供适当的定义。这将确保在调用错误的重载时得到链接错误。
另一种选择是使用CRTP。下面将进一步展示该方法。
成员专门化方法:
#include <string>
class Bar {};
class FooBase
{
public:
FooBase( Bar &ctx ) : _barCtx( ctx ) {};
virtual ~FooBase() {};
protected:
Bar &_barCtx;
};
template< typename T >
class Foo : public FooBase
{
public:
Foo( Bar &ctx ) : FooBase( ctx ) {};
bool doSomething( int a ) { return true; }
// Declared, but not defined.
bool doSomething( std::string &str, int x, float g );
};
class Baz {};
// Declared, but not defined.
template <>
bool
Foo<Baz>::doSomething(int i);
template <>
bool
Foo<Baz>::doSomething(std::string &str, int x, float g) {
return true;
}
int main() {
Bar b;
Foo<int> f1(b);
std::string s;
f1.doSomething(1); // Compiles.
// f1.doSomething(s, 1, 3.14f); // Link error.
Foo<Baz> f2(b);
// f2.doSomething(1); // Link error.
f2.doSomething(s, 1, 3.14f); // Compiles.
}
CRTP方法:
#include <string>
class Bar {};
class Baz {};
template <typename T>
class Spec {
public:
bool doSomething( int a );
};
template <>
class Spec<Baz> {
public:
bool doSomething( std::string &str, int x, float g );
};
class FooBase {
public:
FooBase( Bar &ctx ) : _barCtx( ctx ) {};
virtual ~FooBase() {};
protected:
Bar &_barCtx;
};
template< typename T >
class Foo : public FooBase, public Spec<T> {
public:
Foo( Bar &ctx ) : FooBase( ctx ) {};
};
template <typename T>
bool Spec<T>::doSomething( int a ) {
Foo<T> *fp = static_cast<Foo<T> *>(this);
return true;
}
bool Spec<Baz>::doSomething( std::string &str, int x, float g ) {
Foo<Baz> *fp = static_cast<Foo<Baz> *>(this);
return true;
}
int main() {
Bar b;
std::string s;
Foo<int> f1(b);
f1.doSomething(1);
Foo<Baz> f2(b);
f2.doSomething(s, 1, 3.14f);
}
您可以提供每个重载,然后使用SFINAE启用相关的重载,而不是专门化Foo
:
template< typename T >
class Foo : public FooBase
{
public:
Foo( Bar &ctx ) : FooBase( ctx ) {};
template<
typename U = T,
typename = typename std::enable_if<!std::is_same<U, Baz>::value>::type>
bool doSomething( int a )
{
std::cout << "doSomething( int a )n";
}
template<
typename U = T,
typename = typename std::enable_if<std::is_same<U, Baz>::value>::type>
bool doSomething( std::string &str, int x, float g )
{
std::cout << "doSomething( std::string &str, int x, float g )n";
}
};
(由于不能使用c++ 11,请使用boost版本或您自己的版本替换std::enable_if
和std::is_same
)
这似乎是使用模板专门化的错误地方。模板化类型在声明的任何地方都没有使用,所以它看起来完全是任意的。
我建议使用其他技术
1)为你的输入定义一个抽象基类型,并让doSomething接受它的任何实现。
bool doSomething(DoSomethingParamsBase* params);
或
2)在
之后使用枚举模式参数和可变参数bool doSomething(MODE mode...);
相关文章:
- "error: no matching function for call to"构造函数错误
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 选择要调用的构造函数
- 如何委托派生类使用其父构造函数?
- 构造函数正在调用一个使用当前类类型的函数
- 没有用于初始化C++中的变量模板的匹配构造函数
- 初始化具有非默认构造函数的std::数组项的更好方法
- 当从函数参数中的临时值调用复制构造函数时
- 在c++构造函数中使用随机字符串生成器
- 一对向量构造函数:初始值设定项列表与显式构造
- 从构造函数抛出异常时如何克服内存泄漏
- 我不明白为什么我声明一个空的内部结构并将其传递给构造函数
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 具有默认模板类型的默认构造函数的类型推导
- 使用dynamic_cast和构造函数时出错
- 在c++中使用向量时,如何调用构造函数和析构函数
- 奇怪的构造函数行为