Получить тип с помощью value_type в pertect forward - PullRequest
1 голос
/ 23 апреля 2020

Я создаю функцию, которая идеально подходит для этой функции:

template<typename T>
void push_back_3(T&& container) {
  using containter_val_type = typename T::value_type;
  containter_val_type val = 3;
  container.emplace_back(val);
}

Функция может принимать входные данные контейнера, такие как std::vector, std::list ...

Я знаю выше std контейнер имеет тип-признак реализации value_type.

Так что я просто использую std::vector<T>::value_type или std::list<T>::value_type,

Я получу тип T.

затем

Я демо-программа:

int main(int argc, char const *argv[]) {
  std::vector<int> ivec{1,2,3,4};
  push_back_3(ivec);
  for (std::vector<int>::iterator iter = ivec.begin(); 
        iter != ivec.end(); 
        ++iter) 
  {
    std::cout << *iter << "\n";
  }

  return 0;
}

Но я получил сообщение об ошибке:

> $ clang++ t.cc -o t                                                               
t.cc:11:40: error: type 'std::vector<int, std::allocator<int> > &' cannot be used prior to '::' because it has no members
  using containter_val_type = typename T::value_type;
                                       ^
t.cc:18:3: note: in instantiation of function template specialization 'push_back_3<std::vector<int, std::allocator<int> > &>' requested here
  push_back_3(ivec);
  ^
1 error generated.

Я не знаю, почему я получил выше ошибка.

Ответы [ 2 ]

3 голосов
/ 23 апреля 2020

T выводится как lvalue ссылка, вы должны удалить ссылку с помощью:

typename std::decay_t<T>::value_type;

Пересылка ссылки для lvalue (это так, потому что ivec именованный объект) возвращает T&. Невозможно получить value_type для ссылочного типа.

Демо

2 голосов
/ 23 апреля 2020

Здесь нет никакого смысла в совершенной пересылке, зачем добавлять элементы в контейнер, который будет d ie в }?

Возьмите ссылку lvalue, тогда T будет правильным введите

template<typename T>
void push_back_3(T& container) {
  using containter_val_type = typename T::value_type;
  containter_val_type val = 3;
  container.emplace_back(val);
}

В сторону: вы копируете в аргумент emplace_back, вы также можете

template<typename T>
void push_back_3(T& container) {
  container.emplace_back(3);
}
...