Dzięki za pomoc, wyjaśnienia i wskazówki odnośnie kodu, bo wszystkie okazały się trafne i wartościowe. Od siebie dodam, że potestowałem jeszcze troszkę i okazało się, że taki zupełnie najprostszy fix to zmiana z:
...................
na
template <typename T>
class Test
{
private:
T Data = static_cast<T>(0);
public:
operator const T& () const
{
return Data;
}
const T& operator+=(const auto& tValue) //pobiera const auto& jako parametr.
{
return Data += tValue;
}
};
Zakładam, że w tym drugim przypadku kompilator robi sobie niejawną konwersję i jest zadowolony.
To źle zakładasz.
Takie użycie auto
tworzy ci po prostu szablon, który przyjmuje dowolny typ. To jest równoważne temu:
template<typename U>
const T& operator+=(const U& tValue)
{
return Data += tValue;
}
W moim rozwiązaniu, dodanie konceptu da czytelniejszy bład jeśli szablon zostanie użyty z niewłaściwym typem.
Równocześnie moje rozwiązanie pozostawia ci okienko na dodanie przeładowań tego operatora.
Niejawna konwersja w tym wypadku jest wykonywana wewnątrz szablonu co nie ma wpływu na sposób użuycia szablonu funkcji.
W oryginalnym kodzie niejawna konwersja jest/powinna być wykonywana w ramach dopasowywania argumentu do wywołania funkcji (w ramach overload resolution).
PS. Ta notacja ze zwracanym typem po -> rzeczywiście jest nadal w powszechnym użyciu? Myślałem, że odkąd rozszerzyli możliwości auto w C++14, taki zapis stał się nadmiarowy.
C++14 auto return type, może i jest wygodne, ale jest też niebezpieczne, bo nagle możesz mieć typ zwracany niezgodny z oczekiwaniem. Osobiście preferuje podawać jawnie typ zwracany.