Ane*_*ton 9 c++ templates metaprogramming
我正在尝试使用模板元编程来确定基类.有没有办法自动获取基类而不明确专门为每个派生类?
class foo { public: char * Name() { return "foo"; }; };
class bar : public foo { public: char * Name() { return "bar"; }; };
template< typename T > struct ClassInfo { typedef T Base; };
template<> struct ClassInfo<bar> { typedef foo Base; };
int main()
{
ClassInfo<foo>::Base A;
ClassInfo<bar>::Base B;
std::cout << A.Name(); //foo
std::cout << B.Name(); //foo
}
Run Code Online (Sandbox Code Playgroud)
现在任何自动方法都需要选择第一个声明的基数,并且对于私人基地会失败.
Xeo*_*Xeo 17
它可以用C++ 11和decltype
.为此,当成员从基类继承时,我们将利用指向成员的指针不是指向派生类的指针.
例如:
struct base{
void f(){}
};
struct derived : base{};
Run Code Online (Sandbox Code Playgroud)
该类型的&derived::f
将是void (base::*)()
,不会void (derived::*)()
.这在C++ 03中已经存在,但是如果没有实际指定它就不可能获得基类类型.有了decltype
,它很简单,只需要这个小功能:
// unimplemented to make sure it's only used
// in unevaluated contexts (sizeof, decltype, alignof)
template<class T, class U>
T base_of(U T::*);
Run Code Online (Sandbox Code Playgroud)
用法:
#include <iostream>
// unimplemented to make sure it's only used
// in unevaluated contexts (sizeof, decltype, alignof)
template<class T, class R>
T base_of(R T::*);
struct base{
void f(){}
void name(){ std::cout << "base::name()\n"; }
};
struct derived : base{
void name(){ std::cout << "derived::name()\n"; }
};
struct not_deducible : base{
void f(){}
void name(){ std::cout << "not_deducible::name()\n"; }
};
int main(){
decltype(base_of(&derived::f)) a;
decltype(base_of(&base::f)) b;
decltype(base_of(¬_deducible::f)) c;
a.name();
b.name();
c.name();
}
Run Code Online (Sandbox Code Playgroud)
输出:
base::name()
base::name()
not_deducible::name()
Run Code Online (Sandbox Code Playgroud)
如最后一个示例所示,您需要使用一个实际上是您感兴趣的基类的继承成员的成员.
但是,还有更多缺陷:成员还必须明确地标识基类成员:
struct base2{ void f(){} };
struct not_deducible2 : base, base2{};
int main(){
decltype(base_of(¬_deducible2::f)) x; // error: 'f' is ambiguous
}
Run Code Online (Sandbox Code Playgroud)
没有编译器支持,这是你可以获得的最好的.
我不知道任何基类选择模板,我不确定是否存在或者甚至是个好主意.有许多方法可以破坏可扩展性并违背继承精神.当bar
公开继承时foo
,bar
是 foo
出于所有实际目的,并且客户端代码不应该需要区分基类和派生类.
基类中的公共typedef经常会划伤您可能需要划伤并且更清晰的痒:
class foo { public: typedef foo name_making_type; ... };
int main() {
Foo::name_making_type a;
Bar::name_making_type b;
}
Run Code Online (Sandbox Code Playgroud)
我的解决方案不是真的自动,但我能想到的最好.
侵入式C++ 03解决方案:
class B {};
class A : public B
{
public:
typedef B Base;
};
Run Code Online (Sandbox Code Playgroud)
非侵入式C++ 03解决方案:
class B {};
class A : public B {};
template<class T>
struct TypeInfo;
template<>
struct TypeInfo<A>
{
typedef B Base;
};
Run Code Online (Sandbox Code Playgroud)