2015-10-16 1 views
2

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

#include <boost/process.hpp> 

class A{ 
    std::unique_ptr<boost::process::child> child_; 
    std::unique_ptr<boost::process::pistream> is; 

    A(std::string exec, boost::process::context process_context){ 
     // Stuff that needs to be done first 
     // ... 

     child_ = std::make_unique<boost::process::child>(start_child(exec, process_context)); 
     is = std::make_unique<boost::process::pistream>(child_->get_stdout()); // <- error 

    } 

    boost::process::child start_child(std::string exec, boost::process::context process_context); 
}; 

ошибка, я получаю от этого:

ошибка C2280: 'СТД :: basic_ios> :: basic_ios (константные СТД :: basic_ios> &)': пытается ссылки удаленная функция

Если я правильно понимаю, где-то в этой строке происходит копия, что не допускается. Уникальные указатели не требуются. Я просто использую их, чтобы избежать другой ошибки (без инициализации по умолчанию), но я был бы рад принять предложения как с, так и без них.

+2

'get_stdout' возвращает ссылку' pstream & 'на объект, принадлежащий 'child_'. Вы пытаетесь скопировать 'pstream', который не копируется. Вы можете хранить указатель (raw, non-owning) для него, я полагаю, или просто отбрасывать 'is' и использовать' child _-> get_stdout() 'по мере необходимости. –

ответ

3

Вы можете использовать boost::optional<> для ленивой инициализации.

Live On Coliru

#include <memory> 
#include <boost/optional.hpp> 

struct pistream { }; 
struct child { 
    pistream& get_stdout() { return is; } 
    pistream is; 
}; 
struct context { }; 

class A { 
    std::unique_ptr<child> child_; 
    boost::optional<pistream&> is; 

    A(std::string, context) { 
     // Stuff that needs to be done first 
     // ... 

     child_ = std::make_unique<child>(); 
     is  = child_->get_stdout(); 
    } 
}; 
+0

Добавлена ​​полная демонстрация (после того, как вы заметили, какой член был привязан к какой ссылке ...) ** [Live On Coliru] (http://coliru.stacked-crooked.com/a/4dbf4588b22a02fe) ** – sehe

3

Проблема заключается в том, что std::unique_ptr хочет владение pistream, поэтому он пытается взять копию, которая, как вы обнаружили, не допускается. Если вы думаете об этом, это имеет смысл: вы, конечно же, не хотите, чтобы std::unique_ptr<b::p::pistream> удалял поток _child в свой деструктор.

Самым простым решением было бы просто использовать обычные, не владеющим указатель вместо, скажем:

class A{ 
    std::unique_ptr<boost::process::child> child_; 
    boost::process::pistream* is = nullptr; 

    A(std::string exec, boost::process::context process_context){ 
     // ... 
     child_ = std::make_unique<boost::process::child>(start_child(exec, process_context)); 

     is = &child_->get_stdout(); 
    } 
}; 

Конечно, вы хотите, чтобы проверить, что is не nullptr до фактического его использования, но то же самое верно для unique_ptr.

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