5

我希望能够将继承自的对象的引用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继承自DBMetaDataas 参数的类型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;
}
4

2 回答 2

4

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

非类型、非模板模板参数模板参数应为以下之一: [...]

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

根据同一部分的第 5 段,不允许派生到基础的转换:

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

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

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

于 2012-11-28T14:12:55.840 回答
1

您可以使用 C++11decltype和如下宏:

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

现在,定义一个变量:

DBVAR(_md_u1) _u1;

希望这可以帮助。

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

于 2012-11-28T14:36:29.453 回答