2017-02-21 1 views
0

В основном я хочу, чтобы обеспечить строительство из константных версий Lvalue и ссылочное Rvalue версии:Как бороться с const T & и T &&, создавая одну и ту же подпись?

transform_iterator(const Functor& f, const Iterator& it) : 
      functor(f), 
      iterator(it) 
    {} 

    transform_iterator(Functor&& f, Iterator&& it) : 
      functor(f), 
      iterator(it) 
    {} 

Из того, что я знаю, ссылка Rvalue версия не универсальные ссылки. Несмотря на это, на этом месте вызова:

template <typename InputIt, typename OutputIt> 
std::pair<InputIt, OutputIt> sliding_average(InputIt first, InputIt last, 
        const typename std::iterator_traits<InputIt>::difference_type window_length, 
        OutputIt d_first) 
{ 
    using value_type = typename std::iterator_traits<InputIt>::value_type; 
    auto divide = [&window_length](const value_type& value) 
    { 
     return value/window_length; 
    }; 

    auto iterator = shino::transformer(divide, d_first); //transform_iterator<Functor, Iterator> 

    shino::sliding_window(first, last, iterator, window_length); 
             //^^ pass by value 

компилятор говорит, что ссылка Rvalue версия заканчивает тем, что сопзИте ссылку именующей версии.

Для полноты, вот сайт вызова sliding_average

sliding_average(v.begin(), v.end(), window_length, output.begin()); 

где оба v и output являются векторами междунара и двойников, и window_length является std::size_t.

Когда я удаляю версию const lvalue, код компилируется и работает правильно.

Кроме того, этот код компилируется без проблем с обоими конструкторами:

std::vector<std::string> v{"23", "25", "27"}; //just random numbers 
std::vector<int> output(v.size()); 

auto string_to_int = [](const std::string& x) 
{ 
    return std::stoi(x); 
}; 

auto conversion_iterator = shino::transformer(string_to_int, output.begin()); 

Вопрос: Как это исправить?

+1

Где 'transform_iterator' вызывается с * RValue *? –

+0

@VittorioRomeo, обновленный. – Incomputable

+1

Вы все еще не проходите * rvalue *. 'iterator' является * lvalue *, как' d_first'. Вы забыли «std :: move»? –

ответ

1

Я думаю, что ваше понимание Lvalue с и RValue ы не является правильным.

Вы не вызывая transform_iterator::transform_iterator с RValue где-нибудь в коде вы публикуемую.


auto iterator = shino::transformer(divide, d_first); 
//           ^^^^^^^ 
//           lvalue 

Чтобы вызвать RValue ссылка перегружать, вам нужно RValue!std::move может быть использован, чтобы бросить d_first к RValue эталонным - например:

auto iterator = shino::transformer(divide, std::move(d_first)); 
//           ^^^^^^^^^^^^^^^^^^ 
//           rvalue 

То же самое относится и к коду вы добавили в вашем редактирования:

shino::sliding_window(first, last, iterator, window_length); 
//         ^^^^^^^^ 
//         lvalue 

Вы, вероятно, хотите:

shino::sliding_window(first, last, std::move(iterator), window_length); 
//         ^^^^^^^^^^^^^^^^^^^ 
//         rvalue 

Соответствующие вопросы:

1

В

auto iterator = shino::transformer(divide, d_first); 

Вы всегда будете называть константное ссылочное именующее перегрузку функции. Причина в том, что d_first является именованной переменной. Это означает, что это lvalue, даже если он был передан функции как rvalue. Если вы хотите сделать именованный переменной в RValue вам нужно использовать std::move как

auto iterator = shino::transformer(divide, std::move(d_first)); 
Смежные вопросы