c ++静态多态性/ CRTP,带有访问基class成员的附加模板参数
c++ static polymorphism / CRTP with additional template parameters accessing base class member
我想使用 CRTP 实现静态多态性,并向模板参数添加其他类型。
提供如下场景,如何直接从Derived访问Base成员class?是否可以不指定 Base 的完整类型 class?
#include <iostream>
template<class Derived, class X>
struct Base
{
void set_a( int a ) { _a = a; }
protected:
int _a;
};
template<class X>
struct Derived: public Base<Derived<X>, X>
{
int get_a( )
{
// return Base<Derived<X>,X>::_a; // This works!
return _a; // error: use of undeclared identifier '_a'
}
};
struct foo;
int main()
{
Derived<foo> test;
auto base_p = static_cast< Base<Derived<foo>, foo>* >( &test );
base_p->set_a( 42 );
int a = test.get_a();
std::cout << a << std::endl;
}
g++5.3.1 / clang++3.8.0 输出:
error: use of undeclared identifier '_a'
您可以在 class 中添加 using
声明:
template<class X>
struct Derived: public Base<Derived<X>, X> {
using Base<Derived<X>, X>::_a;
/* ... */
};
不过还是要指定一次。
在Derived
范围内,_a
没有被声明而是被继承,所以你必须写this->_a
在基数class中查找或者显式写Base<Derived<X>, X>::_a
。后者可以用
导入
using Base<Derived<X>, X>::_a;
在Derived
.
的定义中
tl;dr
如果写入 this->_a
,this
会自动向上转换为 Base<Derived<X>, X>*
以匹配内部 operator->
.
如果只写_a
,则执行unqualified name lookup。非限定名称查找是基于范围的,与继承无关。在您的示例中,_a
在 Derived::get_a
中,因此 _a
在
中搜索
Derived::get_a
Derived
- (文件范围)
没有找到_a
,导致编译错误
我想使用 CRTP 实现静态多态性,并向模板参数添加其他类型。
提供如下场景,如何直接从Derived访问Base成员class?是否可以不指定 Base 的完整类型 class?
#include <iostream>
template<class Derived, class X>
struct Base
{
void set_a( int a ) { _a = a; }
protected:
int _a;
};
template<class X>
struct Derived: public Base<Derived<X>, X>
{
int get_a( )
{
// return Base<Derived<X>,X>::_a; // This works!
return _a; // error: use of undeclared identifier '_a'
}
};
struct foo;
int main()
{
Derived<foo> test;
auto base_p = static_cast< Base<Derived<foo>, foo>* >( &test );
base_p->set_a( 42 );
int a = test.get_a();
std::cout << a << std::endl;
}
g++5.3.1 / clang++3.8.0 输出:
error: use of undeclared identifier '_a'
您可以在 class 中添加 using
声明:
template<class X>
struct Derived: public Base<Derived<X>, X> {
using Base<Derived<X>, X>::_a;
/* ... */
};
不过还是要指定一次。
在Derived
范围内,_a
没有被声明而是被继承,所以你必须写this->_a
在基数class中查找或者显式写Base<Derived<X>, X>::_a
。后者可以用
using Base<Derived<X>, X>::_a;
在Derived
.
tl;dr
如果写入 this->_a
,this
会自动向上转换为 Base<Derived<X>, X>*
以匹配内部 operator->
.
如果只写_a
,则执行unqualified name lookup。非限定名称查找是基于范围的,与继承无关。在您的示例中,_a
在 Derived::get_a
中,因此 _a
在
Derived::get_a
Derived
- (文件范围)
没有找到_a
,导致编译错误