Ostatnie pytanie, które zadałem, było czymś, na co natknąłem się, próbując zrozumieć inną rzecz ... której również nie mogę zrozumieć (nie mój dzień).Niejawna konwersja nie dzieje się
To dość długie pytanie, ale przynajmniej mam nadzieję, że to pytanie może okazać się przydatne dla wielu osób, a nie tylko dla mnie.
kod mam jest następujący:
template <typename T> class V;
template <typename T> class S;
template <typename T>
class V
{
public:
T x;
explicit V(const T & _x)
:x(_x){}
V(const S<T> & s)
:x(s.x){}
};
template <typename T>
class S
{
public:
T &x;
explicit S(V<T> & v)
:x(v.x)
{}
};
template <typename T>
V<T> operator+(const V<T> & a, const V<T> & b)
{
return V<T>(a.x + b.x);
}
int main()
{
V<float> a(1);
V<float> b(2);
S<float> c(b);
b = a + V<float>(c); // 1 -- compiles
b = a + c; // 2 -- fails
b = c; // 3 -- compiles
return 0;
}
Ekspresja 1 i 3 działa idealnie, podczas gdy ekspresja 2 nie kompilacji.
Jeśli prawidłowo zrozumiane, co dzieje:
Ekspresja 1
- C jest niejawnie przekształca się
const
stosując standardową sekwencję konwersji (składający się tylko na jednej kwalifikacji konwersja). Wygenerowano V<float>(const S<T> & s)
i tymczasowo wygenerowano obiektconst V<float>
(nazwijmy go: t). Jest już ograniczony, ponieważ jest wartością czasową.- a jest konwertowany na ciąg podobny do c. Wygenerowano
operator+(const V<float> & a, const V<float> & b)
, co daje tymczasowy typconst V<float>
, który możemy nazwać q.- domyślnie wywoływana jest
V<float>::operator=(const & V<float>)
.
Czy jestem OK do tego miejsca? Jeśli zrobiłem nawet najbardziej subtelny błąd, proszę, daj mi znać, bo staram się uzyskać wiedzę na temat odlewania niejawny jak najgłębiej ...
Expression 3
- c jest przekształcone na
V<float>
. W tym celu mamy zdefiniowaną przez użytkownika sekwencję konwersji:
1.1. pierwsza standardowa konwersja:S<float>
doconst S<float>
poprzez konwersję kwalifikacji.
1.2. konwersja zdefiniowana przez użytkownika:const S<float>
naV<float>
przez konstruktor .
1.3 druga standardowa konwersja:V<float>
naconst V<float>
poprzez konwersję kwalifikacji. - domyślnie wywoływana jest
V<float>::operator=(const & V<float>)
.
Wyrażenie 2?
Nie rozumiem, dlaczego występuje problem z drugim wyrażeniem. Dlaczego następująca sekwencja nie jest możliwa?
- C przekształca się
V<float>
. W tym celu mamy zdefiniowaną przez użytkownika sekwencję konwersji:
1.1. początkowa konwersja standard:S<float>
doconst S<float>
poprzez konwersję kwalifikacji.
1.2. konwersja zdefiniowana przez użytkownika:const S<float>
naV<float>
przez konstruktor .
1.3. ostateczna konwersja standardowa:V<float>
naconst V<float>
poprzez konwersję kwalifikacji. - kroki od 2 do 6 są takie same jak w przypadku wyrażania 1.
Po przeczytaniu C++ Standard I chociaż: „hej! może problem musi z 13.3.3.1.2.3! który stanowi:
If the user-defined conversion is specified by a template conversion function, the second standard conversion sequence must have exact match rank.
Ale to nie może być przypadek, ponieważ kwalifikacja konwersja ma dokładnego dopasowania rangę ...
naprawdę nie mam pojęcia ...
Cóż, czy masz odpowiedź lub nie, dziękuję za przeczytanie tutaj :)
Dziękuję bardzo bardzo! Od początku patrzyłem na problem od początku ... dziękuję bardzo za sztuczkę "przyjaciela operatora", myślę, że właśnie to zrobię :) – jmeseguerdepaz
dziękuję, dobrze. kolejny dowód na to, że C++ może być naprawdę brzydki i podły! – Atmocreations
Możesz użyć 'std :: identity' w' 'zamiast' id' –
David