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_NTDBMetaDataDBVar< _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として表現されます(括弧は無視されます) 。ただし、対応するtemplate-parameterが参照である&場合は、[...]は省略されます。 。

同じセクションのパラグラフ5に従い、派生からベースへの変換は許可されていません。

  • オブジェクトへの型参照の非型テンプレートパラメータの場合、変換は適用されません。参照によって参照されるタイプは、template-argumentの(それ以外の場合は同一の)タイプよりもcv修飾されている可能性があります。template-parametertemplate-argumentに直接バインドされ、これは左辺値でなければなりません。

これは、キャストが許可されていないことも意味します。これは、[ &] 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 に答える