1

Given some classes with parameterized constructors, such as:

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

How to properly initialize a tuple of such classes?

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

Not using copy constructor of A or B, and, if possible, not using move-constructor either. C++03 solution preferred, if possible.

Cœur
  • 37,241
  • 25
  • 195
  • 267
shrike
  • 4,449
  • 2
  • 22
  • 38
  • For your edit, you may look at [why-is-there-no-piecewise-tuple-construction](http://stackoverflow.com/questions/11846634/why-is-there-no-piecewise-tuple-construction) – Jarod42 Apr 06 '16 at 22:16
  • If you can make your types movable, you should. There are very few cases where a type should not be movable. (In the standard library, atomics, mutexes, and condition variables are not movable for technical reasons.) If you cannot make your types movable, you might use `std::unique_ptr` as a workaround. – Brian Bi Apr 06 '16 at 22:21
  • @Brian: move-constructor is a possible option that I'd prefer to avoid though, in order for my code to be compilable on non C++11 compliant compiler. Thanks for answer anyway. – shrike Apr 06 '16 at 22:33
  • so... `std::tuple` is fine but move constructors are not? – Brian Bi Apr 06 '16 at 22:36
  • @Brian: He used `boost-tuples` in his tag. – Nicol Bolas Apr 06 '16 at 22:38
  • @Brian: yes, using boost tuples and vc10 compiler – shrike Apr 06 '16 at 22:44
  • If you want a C++03 solution you should indicate that in your question. Same goes for if particular compiler. – M.M Apr 06 '16 at 22:45
  • @M.M: sorry, I indeed should have mentioned clearly that a C++03 solution is prefered (not mandatory though) to a C++11 solution. – shrike Apr 06 '16 at 22:52
  • @Jarod: thanks for the link, I think I'll a to move to vc14... – shrike Apr 06 '16 at 22:53

2 Answers2

4

Can you just add a piecewise constructor for your types? If so, you can create a horrible macro that unpacks and delegates a tuple:

#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)...)                    \
    { }

And just add it to your types:

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)
};

And pass in tuples:

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

Pre-C++11, I don't know that this is possible - you don't have delegating constructors at all. You'd have to either:

  1. Write your own tuple-like class that accepts tuples in its constructor
  2. Add tuple constructors to your types that explicitly initialize the same thing as the non-tuple versions did
  3. Have a tuple of types that are single-argument constructible, like boost::tuple<boost::scoped_ptr<A>, boost::scoped_ptr<B>>(new A(...), new B(...))

(1) is a lot of work, (2) is code duplication and error prone, and (3) involves now having to do allocation all of a sudden.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • FYI: He used [tag:boost-tuples] as a tag, so `std::tuple` is not the intent. – Nicol Bolas Apr 06 '16 at 22:39
  • @Nicol It'd be great if the intent were completely spelled out in the question in one go, rather than incrementally in various comments... – Barry Apr 06 '16 at 22:42
  • @Barry: I thought the tags would have clarified this (no C++11 tag, boost-tuple tag), but I was wrong, sorry. Anyway, thanks for all the available solutions you provided, I'll probably go for solution 3 until I move to C++11. Thanks a lot. – shrike Apr 06 '16 at 23:09
2

You may use the following:

tuple<A,B> tup(A(true, 42), B('*', 4.2));
Jarod42
  • 203,559
  • 14
  • 181
  • 302