6

次の2つの関数テンプレートのオーバーロードがあります。

template<typename T>
optional<T> some(const T& x)
{
    return optional<T>(x);
}

template<typename T>
typename std::enable_if<std::is_rvalue_reference<T&&>::value, optional<T> >::type
some(T&& x)
{
    return optional<T>(std::move(x));
}

完全な転送を介して過負荷を統合する最初の試みは失敗しました:

template<typename T>
optional<T> some(T&& x)
{
    return optional<T>(std::forward<T>(x));
}

error: forming pointer to reference type 'const std::basic_string<char>&'

私の2回目の試みと同じように:

template<typename T>
optional<typename std::remove_reference<T>::type> some(T&& x)
{
    return optional<typename std::remove_reference<T>::type>(std::forward<T>(x));
}

error: no matching function for call to
'std::basic_string<char>::basic_string(gpa::optional<const std::basic_string<char> >)'

過負荷を統一するためのクリーンな方法はありますか、それとも私はそれらを持って生きるべきですか?

4

2 に答える 2

4

私はあなたoptionalに精通していませんが、おそらくあなたは追加する必要があります:

typename remove_const< ... >::type

remove_reference2か所であなたの周り。(2過負荷ソリューションの最初の過負荷(すべてのテストに合格していると思います)は、remove_const宣言時に効果的に実行するためoptional<T>です)。

于 2012-04-18T15:11:41.053 に答える
1

一般に、これを行う最善の方法は、オブジェクトを値で取得し、呼び出し元にそれをコピーするか移動するかを決定させることです。

template<typename T>
optional<T> some(T x)
{
    return optional<T>(std::move(x));
}

呼び出し元が一時的にそれを呼び出すかstd::move、それらの値を使用すると、移動されます。それ以外の場合はコピーされます。

はい、これは追加の 1 つの移動を行うことを意味します (移動がコピーと同じ場合、2 つのコピーを行うことを意味します)。それが重大なパフォーマンスの問題である場合は、2 つのオーバーロードの実装を使用する必要があります。

于 2012-04-18T18:36:16.713 に答える