采用继承类的C ++非类型模板参数

时间:2012-11-28 13:43:32

标签: c++ templates inheritance 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;
}

我可以编译并运行上面的示例但是我需要明确指定继承的类型。

如果我尝试编译它定义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

为什么我无法传递_u1 DBMetaData_NT类型,DBMetaData继承自DBVar< _md_u1 > _u1;作为#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; } 的参数?

有没有办法得到我想要的东西?

谢谢!


编辑:

用@ecatmur建议的函数指针替换模板参数解决了我的问题,我必须注意,我的代码更易读。

{{1}}

2 个答案:

答案 0 :(得分:4)

不幸的是没有。根据14.3.2 模板非类型参数,第1段:

  

非类型,非模板模板参数 template-argument 应为以下之一:[...]

     
      
  • 一个常量表达式,用于指定具有静态存储持续时间[...]的对象的地址,表示(忽略括号)为& id-expression ,但{{如果相应的 template-parameter 是参考,则应省略1 ...}。
  •   

根据相同部分的第5段,允许派生到基本的转化:

  
      
  • 对于对象类型引用的非类型模板参数,不适用任何转换。引用引用的类型可能比 template-argument 的(否则相同)类型更符合cv。 template-parameter 直接绑定到 template-argument ,它应该是左值。
  •   

这也意味着不允许使用强制转换,因为它不是[&] id-expression 的形式,并且不会产生左值。

根据您要完成的任务,您可以通过手动模拟多态性来获得类似的结果,例如:将&初始化为函数的返回值,该函数设置适当的vtable指针或表。

答案 1 :(得分:1)

您可以使用C ++ 11的decltype和以下宏来实现:

#define DBVAR(metadata) DBVar<decltype(metadata), metadata>

现在,定义一个变量:

DBVAR(_md_u1) _u1;

希望这有帮助。

编辑:说实话,我不喜欢你的做法。我宁愿选择静态元数据成员函数或基于非模板的多态性。