2011-08-04 11 views
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を取り、vが暗黙のうちにされています変換される。

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

+0

最小限のスタンドアロンの例はありますか? –

+0

@James:残念ながら、コードは外部プログラムによって自動的に生成され、私は特にそれに精通していないので、わかりません。 – Puppy

答えて

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つのオーバーロードの機能を持っている:あなたは代わりに転送し、単一の機能を持っている必要があります。 、

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

そして、それは私が推測を作ってるんだ(最初のものよりも、より専門であるため、第二1勝:

は、私はこれらがあなたのオーバーロードセット内の2つの変異体があること(ポジティブではない)と考えています私は100%肯定的ではない)。

+0

Tは依然として参照型であり、構築はまだ失敗するため、実際には*問題を解決しません。 – Puppy

+0

@DeadMG:プレースメントの新しいタイプ(おそらく 'std :: remove_cv'?私は100%確実ではない)のために' std :: remove_reference :: type'も必要になると思います。あるいは、2つのオーバーロードが本当に必要な場合は、 'enable_if'を使用して' T &&'オーバーロードが参照型 'T'でインスタンス化されないようにすることができます。 –

+0

はい、あなたは正しいジェームスだと思います。編集中... –

0

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

const Wide::ParsedFile::Identifier* 

として推測し、その型へのconst参照を作成されています最初のオーバーロードで

。これは追加のconstを追加します。