j4x*_*j4x 5 c++ inheritance templates template-specialization
我希望能够传递从DBMetaData另一个类的非类型模板参数继承的对象的引用,DBVar:
#include <iostream>
class DBMetaData
{
public:
virtual const char *description( ) const = 0;
};
class DBMetaData_NT
: public DBMetaData
{
public:
const char *description( ) const
{ return "Useless description."; }
};
#if DO_WHAT_I_WANT
template< const DBMetaData &Metadata >
#else
template< typename MetadataType,
const MetadataType &Metadata >
#endif // DO_WHAT_I_WANT
class DBVar
{
public:
/// Descrição da variavel.
const char *description( ) const
{ return Metadata.description( ); }
};
DBMetaData_NT _md_u1;
#if DO_WHAT_I_WANT
DBVar< _md_u1 > _u1;
#else
DBVar< DBMetaData_NT, _md_u1 > _u1;
#endif // DO_WHAT_I_WANT
int main( )
{
std::cout << "_md_u1.description( ) = " << _md_u1.description( ) << std::endl;
std::cout << "_u1.description( ) = " << _u1.description( ) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我可以编译并运行上面的示例,但我需要显式指定继承的类型.
如果我尝试编译它定义DO_WHAT_I_WANT(我想将类型的引用 - 或指针 - 传递给DBMetaData任何继承类的对象),我得到错误:
templ_inh_arg.cpp:36:15: error: could not convert template argument ‘_md_u1’ to ‘const DBMetaData&’
templ_inh_arg.cpp:36:20: error: invalid type in declaration before ‘;’ token
Run Code Online (Sandbox Code Playgroud)
为什么我不能通过_u1,那是DBMetaData_NT从DBMetaData作为参数继承的类型DBVar< _md_u1 > _u1;?
有什么方法可以得到我想要的东西吗?
谢谢!
编辑:
用@ecatmur建议用函数指针替换模板参数解决了我的问题,我必须注意,我的代码更易读.
#include <iostream>
class DBMetaData
{
public:
/// Descrição da variavel.
virtual const char *description( ) const = 0;
};
class DBMetaData_NT
: public DBMetaData
{
public:
const char *description( ) const
{ return "Useless description."; }
};
typedef const DBMetaData &( *metadata )( );
template< metadata Metadata >
class DBVar
{
public:
/// Descrição da variavel.
const char *description( ) const
{ return Metadata( ).description( ); }
};
const DBMetaData & _md_u1_metadata( )
{
static const DBMetaData_NT _md_u1;
return _md_u1;
}
DBVar< _md_u1_metadata > _u1;
int main( )
{
std::cout << "_md_u1_metadata( ).description( ) = " << _md_u1_metadata( ).description( ) << std::endl;
std::cout << "_u1.description( ) = " << _u1.description( ) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
不幸的是没有。根据 14.3.2模板非类型参数,第 1 段:
非类型、非模板模板参数的模板参数应为以下之一:[...]
- 一个常量表达式,指定具有静态存储持续时间的对象的地址 [...],表示(忽略括号)为
&id-expression,但如果相应的模板参数是引用&,则应省略 [...] 。
根据同一节第 5 段,不允许进行派生到基数的转换:
- 对于对象类型引用的非类型模板参数,不应用任何转换。引用所引用的类型可能比template-argument的类型(否则相同)更具 cv 限定性。template -parameter直接绑定到template-argument,它应该是一个左值。
这也意味着不允许进行强制转换,因为它不是 [ &] id-expression形式,并且不会产生左值。
根据您想要完成的任务,您也许能够通过手动模拟多态性来实现类似的结果,例如初始化为_md_u1设置适当的 vtable 指针或表的函数的返回值。