Wymuś błąd czasu kompilacji, jeśli std :: move spowoduje niezamierzoną kopię?

W swoim przemówieniu GoingNative 2013 Scott Meyers zwrócił na to uwagęstd::move nie ma gwarancji, że wygenerowany kod rzeczywiście wykona ruch.

Przykład:

void foo(std::string x, const std::string y) {
  std::string x2 = std::move(x); // OK, will be moved
  std::string y2 = std::move(y); // compiles, but will be copied
}

Tutaj nie można zastosować konstruktora ruchu, ale z powodu rozdzielczości przeciążenia zostanie użyty normalny konstruktor kopii. Ta opcja awaryjna może być kluczowa dla kompatybilności wstecznej z kodem C ++ 98, ale w powyższym przykładzie najprawdopodobniej nie jest to zamierzone przez programistę.

Czy istnieje sposób na wymuszenie wywołania konstruktora ruchu?

Załóżmy na przykład, że chcesz przenieść ogromną matrycę. Jeśli Twoja aplikacja naprawdę zależy od tego, czy Matrix ma zostać przeniesiony, dobrze byłoby natychmiast uzyskać błąd kompilacji, jeśli ruch nie jest możliwy. (W przeciwnym razie problem z wydajnością może łatwo przejść przez testy jednostkowe, a dowiesz się dopiero po przeprowadzeniu profilowania).

Nazwijmy to gwarantowanym ruchemstrict_move. Chciałbym móc napisać taki kod:

void bar(Matrix x, const Matrix y) {
  Matrix x2 = strict_move(x); // OK
  Matrix y2 = strict_move(y); // compile error
}

Czy to możliwe?

Edytować:

Dziękujemy za wspaniałe odpowiedzi! Były uzasadnione prośby o wyjaśnienie mojego pytania:

Powinienstrict_move nie powiedzie się, jeśli wejście jest stałe?Powinienstrict_move nie powiedzie się, jeśli wynik nie doprowadzi do rzeczywistej operacji przenoszenia (nawet jeśli kopia może być tak szybka jak ruch, np.const complex<double>)?Obie?

Mój pierwotny pomysł był bardzo niejasny: uważałem przykłady Scotta Meyersa za dość alarmujące, więc zastanawiałem się, czy możliwe jest, aby kompilator zapobiegał takim niezamierzonym kopiom.

Scott Meyers wspomniał w swoim wystąpieniu, że ogólne ostrzeżenie kompilatora nie jest opcją, ponieważ spowodowałoby to ogromną liczbę fałszywych alarmów. Zamiast tego chcę przekazać kompilatorowi coś w rodzaju „Jestem w 100% pewien, że musi to zawsze skutkować operacją przenoszenia, a kopia jest zbyt droga dla tego konkretnego typu”.

Tak powiedziałbym to bezceremonialniestrict_move powinien zawieść w obu przypadkach. Tymczasem nie jestem pewien, co byłoby najlepsze. Kolejne aspekty, których nie rozważałem, tonoexcept.

Z mojej strony dokładna semantykastrict_move są otwarte. Wszystko, co pomaga zapobiec niemym błędom w czasie kompilacji bez poważnych wad, jest w porządku.

questionAnswers(3)

yourAnswerToTheQuestion