0

クラスがありvariantます。コンストラクターのペアがあります。

/// Construct and fill.
template <typename T>
inline
variant (const T& t)
{
  YYASSERT (sizeof (T) <= S);
  new (buffer.raw) T(t);
}

template <typename T>
inline
variant (T&& t)
{
  YYASSERT (sizeof (T) <= S);
  new (buffer.raw) T(std::move(t));
}

このコードでこれらのコンストラクターを呼び出しました。

parser::symbol_type
parser::make_IDENTIFIER (const Wide::ParsedFile::Identifier*& v)
{
return symbol_type (token::IDENTIFIER, v);
}

symbol_typevariantこの特定のコンストラクターの 2 番目の引数としてa を取り、v暗黙的に変換されます。

ただし、MSVC は他のコンストラクターを使用する代わりに右辺値参照コンストラクターを使用しようとするためnew、参照しようとするとコンパイル エラーが発生します。それはなぜですか、どうすればそれを止めることができますか?

4

2 に答える 2

3

通常、テンプレート化されT&&た関数をオーバーロードしないでください。代わりに、転送する単一の関数が必要です。

template <typename T>
inline
variant (T&& t)
{
  typedef typename std::remove_reference<T>::type Tr;
  YYASSERT (sizeof (Tr) <= S);
  new (buffer.raw) Tr(std::forward<T>(t));
}

これには、間違ったものを選択する問題を回避しながら、2 つのオーバーロードの機能があります。

これらは、オーバーロード セットの 2 つのバリアントであると思います (肯定的ではありません)。

varaint<const Wide::ParsedFile::Identifier*>(const Wide::ParsedFile::Identifier*const&)
varaint<const Wide::ParsedFile::Identifier*&>(const Wide::ParsedFile::Identifier*&)

そして、2 つ目は最初のものよりも専門的であるため、勝ちます (私は経験に基づいた推測を行っています。100% 肯定的ではありません)。

于 2011-08-04T16:20:30.073 に答える
0

const指定子は関数内と最初のコンストラクター内の異なる場所にあるため、2 番目のテンプレートの方が適しています。

最初のオーバーロードでは、T が次のように推定されます。

const Wide::ParsedFile::Identifier*

そして、その型への const 参照を作成します。これにより、追加の const が追加されます。

于 2011-08-04T16:27:33.243 に答える