6

Mam dwóch następujących funkcji szablonu przeciążeniem:jednoczącym const T & i T && przeciąża

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)); 
} 

Moja pierwsza próba ujednolicenia przeciążeń za pośrednictwem doskonałego spedycji failed:

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>&' 

jak moja druga próba:

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> >)' 

Czy istnieje czysty sposób na zunifikowanie przeciążenia, czy powinienem po prostu żyć z ich posiadaniem?

+1

Powinieneś podać definicję tego, czym jest "opcjonalne <>". –

+0

Jest to w zasadzie zabawkowy klon 'boost :: optional'. – fredoverflow

+1

... A jednak pytanie brzmi: czy możesz podać definicję? Mam wrażenie, że problemem jest interfejs "opcjonalny" (tzn. Idealne przekazywanie jest rozwiązaniem dla "niektórych", może być konieczne dostosowanie go do "opcjonalne"). –

Odpowiedz

1

Ogólnie, najlepszym sposobem na to jest do podjęcia obiektu przez wartość i niech rozmówcę zdecydować, czy skopiować lub przenieść go:

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

Jeśli rozmówca nazywa to z tymczasowym lub używa std::move na ich wartości, a następnie jest przenoszony. W przeciwnym razie jest kopiowany.

Tak, oznacza to, że wykonasz jeden dodatkowy ruch (który, jeśli ruch jest taki sam jak kopiowanie, oznacza wykonanie dwóch kopii). Jeśli jest to dla ciebie znaczący problem z wydajnością, musisz użyć dwóch implementacji przeciążenia.

4

nie jestem zaznajomiony ze swoimi optional, ale być może trzeba dodać:

typename remove_const<...>::type 

wokół remove_reference w dwóch miejscach. (ponieważ twoje pierwsze przeciążenie twojego 2-przeciążeniowego rozwiązania - które, jak zakładam, przepuszcza wszystkie twoje testy - skutecznie wykonuje remove_const, gdy deklarujesz optional<T>).

+0

Nie powinno to być 'remove_cv' tylko być po bezpiecznej stronie? – pmr

+1

Jeśli to jest pożądane. Obecne rozwiązanie 2-przeciążeniowe po prostu odrzuca wartości o zmiennej lotności. Trudno mi powiedzieć, co jest pożądane, bez pełnego przykładu kodu. –

Powiązane problemy