Использование back_inserter для создания вектора из одного члена структуры - PullRequest
1 голос
/ 21 января 2020

Я хотел бы знать, возможно ли использовать std::back_inserter для создания вектора только одного элемента из более сложной структуры. Например, в следующем коде:

struct Person {
  std::string first_name;
  std::string last_name;
  int id;
};
std::vector<Person> people;
// Populate 'people'...

// Extract last names into single vector
std::vector<std::string> last_names;
std::copy(begin(people), end(people), std::back_inserter(last_names)); // <... ?

Единственное решение, которое я нашел до сих пор, - это создание оператора приведения Person -> std::string:

struct Person {
  // ...
  operator std::string() const { return last_name; }
};

Но это не хорошо решение, если я хочу извлечь first_name и last_name в два вектора, не говоря уже о том, как непонятно становится такое неявное преобразование.

Есть ли способ указать std::back_inserter, как создать элемент для вставки? Есть ли другой способ создать такой вектор? Очевидно, я имею в виду не грубый способ:

std::vector<std::string> last_names;
last_names.reserve(people.size());
for (const auto& person : people) {
  last_names.push_back(person.last_name);
}

, а какой-то <algorithm> -подобный;)

Я бы предпочел ответ только на C ++, но я Я открыт для поддержки решений, если это необходимо.

Ответы [ 2 ]

6 голосов
/ 21 января 2020

Вместо этого следует использовать std::transform с объектом функции унарной операции, чтобы выполнить преобразование для каждого элемента. например,

std::transform(std::begin(people), 
               std::end(people), 
               std::back_inserter(last_names), 
               [](const Person& person) { return person.last_name; }
              );
1 голос
/ 21 января 2020

Просто чтобы добавить альтернативы, вы также можете использовать std/boost::bind

  // Extract first names into single vector
  std::vector<std::string> last_names;

  last_names.reserve(people.size());
  std::transform(people.begin(), people.end(), std::back_inserter(last_names), 
                 std::bind(&Person::last_name, std::placeholders::_1));

См. Здесь

...