模板元代码和私有成员
Template meta-code and private members
我想做这样的事情:
template <typename T>
class Foo
{
...
public:
void DoSomething()
{
compile_time_if (T is ClassA)
{
m_T.DoThingOne();
m_T.DoThingTwo();
}
DoSomeFooPrivateThing();
m_T.DoThingThree();
}
T m_T;
};
在这种情况下,我知道所有有效的T
都实现DoThingThree
,但只有ClassA
实现DoThingOne
和DoThingTwo
。这不是鸭子类型的事情,我只想为ClassA
做这额外的部分,我不想将这些方法添加到其他可能的T
s中。我不能进行强制转换,因为可能的T
s不是继承类型。
我知道我可以使用一个外部助手模板来适应这个:
template <typename T>
void Foo_DoSomething(T& t)
{
t.DoThingThree();
}
template <>
void Foo_DoSomething(ClassA& t)
{
t.DoThingOne();
t.DoThingTwo();
t.DoThingThree();
}
template <typename T>
class Foo
{
...
public:
void DoSomething()
{
Foo_DoSomething(m_T);
}
...
};
然而,现在这个外部模板无法访问Foo
的私有成员(不能调用DoSomeFooPrivateThing
),这限制了它的功能,而且它公开暴露在外部,这并不好看。(把外部方法变成朋友只会让事情变得更糟。)
另一个看似合理的选择是在内部实现:
template <typename T>
class Foo
{
...
public:
void DoSomething()
{
DoSomethingImpl(m_T);
}
...
private:
template <typename T2>
void DoSomethingImpl(T2& t)
{
DoSomeFooPrivateThing();
t.DoThingThree();
}
template <>
void DoSomethingImpl(ClassA& t)
{
t.DoThingOne();
t.DoThingTwo();
DoSomeFooPrivateThing();
t.DoThingThree();
}
...
};
但这需要复制外部模板类型和参数。这可能是可以接受的,但感觉还是有点奇怪。遗憾的是,它实际上并没有编译(至少在GCC中没有,因为它反对类内的专业化)。
有更好的方法吗?
我认为最后一个选项是最好的。
代替
template <>
void DoSomethingImpl(ClassA& t)
{
t.DoThingOne();
t.DoThingTwo();
DoSomeFooPrivateThing();
t.DoThingThree();
}
您可以使用(此处无需使用template
):
void DoSomethingImpl(ClassA& t)
{
t.DoThingOne();
t.DoThingTwo();
DoSomeFooPrivateThing();
t.DoThingThree();
}
第一个解决方案:正如您所说,我们可以这样做:
template <typename T> class Foo{
public:
void doSomething(){
doSomething(std::is_same<T,A>());
}
private:
void doSomething(std::true_type){
cout<<"A do"<<endl;
}
void doSomething(std::false_type){
cout<<"any other do"<<endl;
}
};
第二个解决方案:因为模板类Foo只有一个模板参数,所以我们可以直接进行这样的显式专门化。
template <typename T> class Foo{
public:
void doSomething(){
cout<<"any other do..."<<endl;
}
};
template<> void Foo<A>::doSomething(){
cout<<"A do"<<endl;
}
Thrid解决方案:也许这不是一个好办法,我们可以这样做,这种方式(SFINAE)使用C++11或boost enable_if。当类型与A相同时,编译器会自动选择所需的类。
#include <iostream>
using namespace std;
class A {};
template <typename T,typename Enable = void>
class Foo
{
public:
void DoSomething()
{
cout<<"anyother do"<<endl;
}
private:
T m_T;
};
template <typename T> class Foo<T, typename enable_if<is_same<T,A>::value>::type >
{
public:
void DoSomething()
{
cout<<"A do"<<endl;
}
private:
T m_T;
};
更多:
如果两个Foo有很多相同的东西,我们可以为它创建这样的基类:
template <typename T> class BaseFoo{
...
};
和两个从BaseFoo派生的模板类,如下所示:
template <typename T,typename Enable = void>
class Foo:public BaseFoo<T>{...}
template <typename T> class Foo<T, typename enable_if
<is_same<T,A>::value>::type >:public BaseFoo<T>{...}
我已经习惯了你的最后一个解决方案,所以它对我来说并不奇怪。
如果你喜欢,你可以一直做
void DoSomethingImpl(T&t, std::true_type){...}
和
void DoSomethingImpl(T&t, std::false_type){...}
然后
DoSomethingImpl(m_T, std::is_same<T, ClassA>{});
这在功能上是等效的,但如果需要扩展功能,也可以进行更复杂的决策。
- 删除C++继承中虚拟类成员的代码重复
- 如何定义一个没有重复代码的继承的 const 类成员函数?
- 为什么第一个代码块产生垃圾值,而第二个代码块将类成员的值相加?
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- 避免易失性和非易失性成员函数的代码重复
- 错误:类没有名为"ThisW"的成员;你是说"这个"吗?但是代码没有说"ThisW",它已经说了"This"
- 重构类:无法将派生类中成员函数的公共代码移回基类
- 如何避免大多数成员功能相同的代码重复
- 我写了一个类,它总是将其函数参数委托给它的成员,我该如何改进代码
- 从C++代码中直接读取成员属性
- 如何避免将 const 和非 const 成员函数输入到模板中的代码重复
- s.compare 成员函数在下面的C++代码中的行为如何?
- 如何基于构造函数参数模板化类成员函数的代码
- 如何在析构函数中执行一些代码*在*成员被销毁之后
- 如何使用 gcc 内联汇编器代码访问成员变量
- 带有布尔数组成员的 C++ 结构.如何在主代码中使用
- 如何打包结构的成员以实现高效的跨平台代码
- 设备代码中的CUDA类静态成员的成语
- 在通用模板代码中初始化聚合成员
- C函数调用C 成员函数 - 其中C代码与C编译器编译