2014-11-21 1 views
1

Я хочу использовать vector::emplace по умолчанию построить без копируемых и без назначаемой объекта, а затем использовать специальные методы объекта, используя итератор на вновь созданный объект. Обратите внимание, что конструкторы класса без параметров не являются конструкторами по умолчанию. Простой пример:Emplacing в векторе, используя конструктор по умолчанию

#include <iostream> 
#include <vector> 
using namespace std; 

class Test { 
public: 
    Test() {} 
private: 
    Test(const Test&) = delete;    // To make clas un-copyable. 
    Test& operator=(const Test&) = delete; 

    int a_; 
}; 

int main() { 
    vector<Test> test_vec; 
    test_vec.emplace_back();  // <---- fails 

    return 0; 
} 

vector::emplace() создает новый объект, но требует аргументов не по умолчанию конструктора. vector::emplace_back() будет построен в конце вектора.

Есть ли способ заменить конструкцию по умолчанию. Есть ли способ использовать кусочную конструкцию или переадресацию по умолчанию, возможно, используя std::piecewise_construct, как есть для карт? Например, в случае карт мы можем использовать:

std::map<int,Test> obj_map; 
int val = 10; 
obj_map.emplace(std::piecewise_construct, 
       std::forward_as_tuple(val), 
       std::forward_as_tuple()); 

Есть ли что-то подобное для векторов?

+0

Является ли ваш тип движимым? – dyp

+0

Да, но он не может быть назначен или скопирован. См. Пример [здесь] (http://ideone.com/49LKaP).Использование 'emplace_back()' приводит к ошибке компиляции. –

+0

@RizwanC Эта ошибка связана с тем, что тип не * подвижный *. Разработанный пользователем конструктор копирования подавляет генерацию конструктора перемещения по умолчанию. Вам нужно объявить конструктор перемещения по умолчанию (и переместить-присваивание, если хотите), после чего вам не нужны операции удаления копии, так как объявление операций перемещения будет подавлять неявное генерирование копий. – Casey

ответ

2

Как отметил @dyp и @Casey в комментариях, std::emplace не будет работать для векторов класса Test, как класс также не подвижный, потому что «пользователь объявленной конструктор копирования подавляет генерацию перемещения по умолчанию конструктор "(@Casey).

Чтобы использовать здесь emplace, класс должен быть подвижным. Мы можем сделать это путем явного определения (и недобросовестный) переход Конструкторы:

public: 
    Test(Test&& other) = default; 
    Test& operator=(Test&& other) = default; 

Это также косвенно делает класс не-копируемые «после провозглашения операции перемещения будет подавлять неявную генерацию копий» (@Casey)

Теперь мы можем использовать std::emplace_back(), а затем использовать vector::back() для вызова методов только что созданного объекта.

0

Для map, легко:

std::map<int, Object> obj_map; 
obj_map[10]; // default-constructs an object with key 10 

В противном случае, что у вас есть тоже работает:

obj_map.emplace(std::piecewise_construct, 
       std::forward_as_tuple(10), 
       std::forward_as_tuple(args, to, construct, with)); 

[править] эквивалент vector является emplace_back:

obj_vector.emplace_back(); // default construct 
obj_vector.emplace_back(args, to, std::move(construct), with); // forward these 
+1

Понятно, что вы можете использовать 'std :: piecewise_construct' для карт. Однако мой вопрос заключается в том, чтобы делать то же самое для векторов. Наверное, я также оставил некоторую информацию из вопроса (которую я сейчас редактировал): Обратите внимание, что тип не копируется или не присваивается, поэтому использование emplace с другим объектом не подходит. –

+0

@RizwanC А, я не понял ваш вопрос. Обновлен для 'vector'. – Barry

5

vector::emplace_back() будет построен в конце вектора, но также потребует аргументов.

Пакеты параметров могут быть пустыми. Таким образом, вариационный шаблон emplace_back можно вызывать без аргументов; То есть

vector<VeryLimitedClass> vec; 
vec.emplace_back(); 

Является действительным кодом, который инициализирует объект типа VeryLimitedClass через конструктор по умолчанию и «emplaces» это в задней части vec.

+0

@dyp ... вы точно знаете, что я имел в виду. Я не хочу путать ОП со стандартной терминологией. :) – Columbo

+0

Интересно, что нет никакой гарантии, какая инициализация происходит ни от вектора, ни от требований распределителя. Но да, это, вероятно, не сильно заботит. - Я не поддержал этот ответ, так как не уверен, что мы уже знаем всю картину. Если OP имеет не подлежащий копированию и неизменный тип, 'emplace' не может быть использован. – dyp

+1

@dyp Вы уверены, что первая часть вашего последнего комментария? – Columbo

Смежные вопросы