Search code examples
c++templatesvariadic-templatesrvalue-reference

Constructor consuming a variable number of rvalue references


I wish to create an object A that can be constructed by either copying or moving a variable number of B objects. Something like this:

    class B {}
    
    class A {
        A(B&& operand1, B&& operand2, ... B&& operandk) {
           // move construct A
        }
        
        A(B& operand1, B& operand2, ... B& operandk) {
           // copy construct B
        }
    }

I can't seem to identify a way to store r-value references in any sort of iterable container to accomplish this. I've read about std::reference_wrapper but it doesn't seem to allow for r-values. Is there a way to accomplish something like this, or is there a reason I shouldn't be trying to do this at all? Thanks very much.


Solution

  • When you need an object to own, just take it by value. The caller can move-construct or copy-construct the arguments depending on whether they need to retain a copy of the objects they're going to give the constructor.

    And -- even better -- this way they can move-construct some of the objects but not others.

    In the constructor, you can freely move-construct your A subobjects using the B objects in the initializer list since you know the caller will have already copied anything that needs copying.

    To accept a variable number of arguments, just have your constructor be a template accepting a parameter pack, and the arguments by value:

    class A {
    public:
        template <typename... T>
        A(T ...);
    };
    

    In the implementation, you can do whatever you need to after move-constructing a B from each argument. This will cause the constructor template to fail to instantiate if the arguments cannot all be used to create a B:

    template <typename... T>
    A::A(T ... args) {
        (... , do_something_with_a_B(B{std::move(args)}));
    }