C++ i std::forward

0

Na podstawie odpowiedzi tutaj https://stackoverflow.com/que[...]1/advantages-of-using-forward jest fragment "N arguments require 2^N combinations, a nightmare. We'd like to do this automatically." No i fajnie, więc użyjmy std::forward tutaj przykładowy kod: https://ideone.com/Vm49Rx Jak widać nie musiałem robić 2^N kombinacji i bez std::forward można się obejść. I teraz pytanie czemu tak się stało?

1

W tym przypadku nie obsługujesz (w pełni) wszystkich kombinacji rvalue/lvalue, i potencjalnie robisz kopię tam, gdzie jej robić nie trzeba. Ot, cała filozofia, nic nie obszedłeś, równie dobrze mogłeś pójść drogą C++03 i zaoferować wyłącznie przeładowanie z const referencjami.

0

No dobra to dodałem żeby nie było żadnego kopiowania, przenoszenia:

A(const A&) = delete;
A(A&& other) = delete;
A& operator=(const A& other) = delete;
A& operator=(A&& other) = delete;

Ale rezultat jest ten sam(Bo chyba ten kod powinien zablokować tworzenia potencjalnych kopii?). Więc jak to powinno wyglądać poprawnie?

0

Masz to opisane na stacku, ale weźmy podobny przykład jeszcze raz:

struct foo
{
    std::string bar, baz, qux;
    foo(std::string const& bar, std::string const& baz, std::string const& qux):
        bar{bar}, baz{baz}, qux{qux} {}
    foo(std::string const& bar, std::string const& baz, std::string && qux):
        bar{bar}, baz{baz}, qux{std::move(qux)} {}
    foo(std::string const& bar, std::string && baz, std::string const& qux):
        bar{bar}, baz{std::move(baz)}, qux{qux} {}
    foo(std::string const& bar, std::string && baz, std::string && qux):
        bar{bar}, baz{std::move(baz)}, qux{std::move(qux)} {}
    foo(std::string && bar, std::string const& baz, std::string const& qux):
        bar{std::move(bar)}, baz{baz}, qux{qux} {}
    foo(std::string && bar, std::string const& baz, std::string && qux):
        bar{std::move(bar)}, baz{baz}, qux{std::move(qux)} {}
    foo(std::string && bar, std::string && baz, std::string const& qux):
        bar{std::move(bar)}, baz{std::move(baz)}, qux{qux} {}
    foo(std::string && bar, std::string && baz, std::string && qux):
        bar{std::move(bar)}, baz{std::move(baz)}, qux{std::move(qux)} {}
};

tego odpowiednikiem jest

struct foo
{
    std::string bar, baz, qux;
    template<typename T, typename U, typename V>
    foo(T&& bar, U&& baz, V&& qux):
        bar{std::forward<T>(bar)},
        baz{std::forward<U>(baz)},
        qux{std::forward<V>(qux)}
    {}
};

Jeśli podasz tylko 2 z podanych wyżej konstruktorów nie jest to bezpośrednim odpowiednikiem i "obejściem" czegokolwiek.

Jeśli mowa o obejściach to raczej

struct foo
{
    std::string bar, baz, qux;
    foo(std::string bar, std::string baz, std::string qux)
        bar{std::move(bar)},
        baz{std::move(baz)},
        qux{std::move(qux)}
    {}
};

Przy czym to nie jest 1:1.

0

Dzięki!

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0