2016-04-06 1 views
1

Учитывая некоторые классы с параметризованными конструкторами, такие как:Как инициализировать кортеж нестандартных объектов, не подлежащих копированию?

class A 
{ 
public: 
    A(bool b, int i) { /*...*/ } 
private: 
    A(const A&) {} 
}; 
class B 
{ 
public: 
    B(char c, double d) { /* ... */ } 
private: 
    B(const B&) {} 
}; 

Как правильно инициализировать кортеж таких классов?

boost::tuple<A,B> tup(/* ??? */); 

Не использовать конструктор копирования A или B и, если возможно, не использовать конструкцию move-constructor. Предпочтительно, если возможно, решение C++ 03.

+0

Для редактирования вы можете посмотреть [почему-есть-нет-кусочно-tuple-construction] (http://stackoverflow.com/questions/11846634/why-is-there-no-piecewise-tuple -конструкция) – Jarod42

+0

Если вы можете сделать ваши типы подвижными, вы должны. Очень мало случаев, когда тип не должен быть подвижным. (В стандартной библиотеке атомы, мьютексы и переменные условия не могут быть перемещены по техническим причинам.) Если вы не можете сделать ваши типы подвижными, вы можете использовать 'std :: unique_ptr ' как обходной путь. – Brian

+0

@Brian: move-constructor - это возможный вариант, который я бы предпочел избежать, чтобы, чтобы мой код был компилируемым на компиляторе, отличном от C++ 11. Спасибо за ответ в любом случае. – shrike

ответ

3

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

#define CONSTRUCT_FROM_TUPLE(CLS)      \ 
    template <class... Ts>        \ 
    CLS(std::tuple<Ts...> const& tup)     \ 
     : CLS(tup, std::index_sequence_for<Ts...>{}) \ 
    { }            \ 
                 \ 
    template <class Tuple, size_t... Is>    \ 
    CLS(Tuple const& tup, std::index_sequence<Is...>) \ 
     : CLS(std::get<Is>(tup)...)     \ 
    { } 

и просто добавить их к типам:

struct A { 
    A(bool, int) { } 
    A(const A&) = delete; 
    CONSTRUCT_FROM_TUPLE(A) 
}; 

struct B { 
    B(char, double) { } 
    B(const B&) = delete; 
    CONSTRUCT_FROM_TUPLE(B) 
}; 

И пройти в кортежах:

std::tuple<A, B> tup(
    std::forward_as_tuple(true, 42), 
    std::forward_as_tuple('x', 3.14)); 

Pre-C++ 11, я не знаю, что это возможно - у вас нет делегирования конструкторов вообще. Вы бы либо:

  1. Оставить свой tuple -как класса, который принимает кортежи в своем конструкторе
  2. Добавить кортежи конструкторов ваших типов, которые явно инициализировать то же самое, что и не-кортеж версия сделала
  3. есть кортеж типов, которые являются одним аргументом конструктивен, как boost::tuple<boost::scoped_ptr<A>, boost::scoped_ptr<B>>(new A(...), new B(...))

(1) много работы, (2) являются дублирование кода и ошибки, и (3) включает в себя в настоящее время приходится делать выделение вдруг.

+0

FYI: Он использовал [tag: boost-tuples] как тег, поэтому 'std :: tuple' не является целью. –

+0

@Nicol Было бы здорово, если бы намерения были полностью изложены в вопросе за один раз, а не поэтапно в разных комментариях ... – Barry

+0

@Barry: Я думал, что теги прояснили бы это (нет тега C++ 11 , тег boost-tuple), но я ошибся, извините. В любом случае, спасибо за все доступные вами решения, я, вероятно, займусь решением 3, пока не перейду на C++ 11. Большое спасибо. – shrike

2

Вы можете использовать следующее:

tuple<A,B> tup(A(true, 42), B('*', 4.2)); 
+0

Спасибо за ответ. Я забыл упомянуть, что конструктор копирования нельзя использовать. Вопрос отредактирован. В любом случае, спасибо за ваш ответ. – shrike

+3

Обратите внимание, что если возможно, он будет использовать конструктор перемещения. – Jarod42

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

  • Нет связанных вопросов^_^