Шаблон универсальной ссылки в с ++ не компилируется - PullRequest
0 голосов
/ 25 мая 2018

Мне сложно понять, почему мой код не компилируется здесь.Я получаю много сообщений об ошибках из стандартной библиотеки в соответствии с

main3.cpp:10:20:   required from ‘void addAndCout(T&&) [with T = const char (&)[11]]’
main3.cpp:20:28:   required from here
/usr/include/c++/5/bits/alloc_traits.h:450:27: error: forming pointer to reference type ‘const char (&)[11]’
       using pointer = _Tp*;
                           ^
/usr/include/c++/5/bits/alloc_traits.h:453:39: error: forming pointer to reference type ‘const char (&)[11]’
       using const_pointer = const _Tp*;

Это не имеет смысла для меня, так как я думал, что T &&, когда T не был выведен, является универсальнымссылка, которая должна быть в состоянии связать с rvalue или lvalue.В этом примере я пытаюсь скопировать раздел из «Эффективного современного C ++» Скотта Мейера, где я читал об универсальных ссылках. Фотография примера из книги

Мне просто интересно, почему это не скомпилируется или что мне здесь не хватает, поскольку, насколько я могу судить, это фактически то же самое дляпример.

#include <iostream>
#include <vector>
#include <string>
using std::cout;
using std::endl;

template<typename T>
void addAndCout(T &&name)
{
    std::vector<T> v;

    cout << name << endl;
    v.emplace_back(std::forward<T>(name));
}

int main(int argc, char **argv)
{
    std::string name {"test"};

    addAndCout(std::string("rvalue")); // FINE      move rvalue instead of copying it
    addAndCout("New string");          // ERROR     make a new string instead of copying
    addAndCout(name);                  // ERROR     copy lvalue
}

Ответы [ 2 ]

0 голосов
/ 25 мая 2018
  • Когда вы делаете addAndCout(std::string("rvalue"));, это rvalue-ссылка, а параметром шаблона T является std :: string и this::std::vector<std::string> v;, который действителен.
  • Но когда вы делаете addAndCout("New string"); T выводится какссылка на массив const char, и у вас не может быть вектора ссылок
  • И когда вы делаете addAndCout(name);, вы передаете l-значение ref, а T становится std::string& и подобным, которого у вас не может бытьвекторы ссылок.
0 голосов
/ 25 мая 2018

Не может быть ни vector ссылок, ни вектора массивов в стиле C.Строка std::vector<T> v; не компилируется, если аргумент является массивом lvalue и / или массивом стиля C.

Ваш код отличается от книги тем, что вы делаете std::vector<T> v;, тогда как книга не делает.

Для поддержки использования addAndCout(name); вы можете изменить определение вектора на:

std::vector< typename std::remove_cv<typename std::remove_reference<T>::type>::type > v;

(remove_cv означает, что вектор константных объектов тоже не может быть).

Для поддержки массива в стиле C было бы проще добавить дополнительную перегрузку:

template<typename T, size_t N>
void addAndCout(T (&name)[N])
{
     // do whatever...
}
...