Не должны ли функции begin () и end () вызываться только для ссылок на l-значения класса? - PullRequest
2 голосов
/ 16 марта 2019

Рассмотрим следующий фрагмент кода:

struct iterator{};

struct foo {
    iterator begin() &{
        return {};        
    }
    iterator end() &{
        return {};        
    }
};

struct bar {
    iterator begin(){
        return {};        
    }
    iterator end(){
        return {};
    }
};

void baz(){
    //this obviously wouldn't compile
    //vvvvvvvvvvvvv
    //foo().begin();
    bar().begin();
}

Это, конечно, игрушечный пример, структуры foo и bar эмулируют работу коллекций C ++.Мой вопрос: есть ли хорошие аргументы для того, чтобы функции begin и end могли вызываться для ссылок на r-значения (как в bar)?Или я должен следовать идее foo, чтобы сделать код более безопасным?Насколько я знаю, получение итератора из временной коллекции вообще плохая идея.Но с другой стороны, все коллекции в STL работают как для ссылок на l-, так и на r-значения, поэтому, возможно, я что-то упускаю

живой пример

1 Ответ

3 голосов
/ 16 марта 2019

Я предполагаю, что вы думаете о ситуации, когда begin вызывается для prvalue, время жизни которого заканчивается, поэтому это приводит к тому, что foo().begin() является висящим указателем, поскольку временный foo() был разрушен.

Но это не всегда так. Тот факт, что значение является значением prvalue или xvalue, не означает, что при вызове foo::begin() и iterator::operator* объект foo будет уничтожен или опустошен. Учтите это:

#include <utility>

template<class T> void do_something_with(const T&);

template<class T>
void baz(T&& it) {
    auto begin = std::forward<T>(it).begin();
    auto end = std::forward<T>(it).end();
    for (; begin != end; ++begin) {
        do_something_with(*begin);
    }
}

void bar() {
    baz(foo());
    // Calls `baz<foo>(foo())`, with `decltype(it)` being `foo&&`
}

Но это вполне допустимый вариант использования. Не путайте тип значения (rvalue или lvalue) с временем жизни.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...