Class with templated constructor as well as copy and move constructor

前端 未结 1 1122
Happy的楠姐
Happy的楠姐 2021-01-14 17:49

This question is a follow up to this one: Explicit template specialization for templated constructor of templated class The answers given in the other question are of course

1条回答
  •  耶瑟儿~
    2021-01-14 18:04

    1) Can you explain why the program does not behave as I expected?

    On this line:

    var i1(i0); // expect 'copy' -> get 'general rvalue'

    The var(T&&) constructor is instantiated with T substituted with var&, i.e. producing a constructor with this signature:

    var(var&);
    

    That constructor is a better match than the implicit copy constructor var(const var&) because i0 is non-const.

    Similarly for:

    var i3(s); // expect 'general lvalue' -> get 'general rvalue'

    s is non-const, so the var(T&&) constructor is instantiated with T substituted with std::string&, producing a constructor with the signature:

    var(std::string&);
    

    For a non-const argument that constructor is a better match than the other constructor template, which produces:

    var(const std::string&);
    

    You need to realise that the var(T&&) constructor is not a "general rvalue" constructor, because T&& can match any type including lvalues.

    See Universal References in C++11 for more details.

    2) How can I make the program to call the copy and move constructor of var when it gets a var and the templated constructors otherwise?

    Constrain the templates so they don't accept any type.

    template
      using Is_a_var = std::is_same::type, var>;
    
    template
      using Enable_if_not_a_var = typename std::enable_if::value>::type;
    
    template>
    var(T&& t) {
        std::cout << "general value" << std::endl;
    }
    

    I would also add defaulted copy/move constructors, to be clear to readers you want them:

    var(const var&) = default;
    var(var&&) = default;
    

    3) And finally, I'm trying to put the two templated constructors into one handling both lvalues and rvalues and forwarding them to another function using std::forward - how could this look like?

    Don't. The var(T&&) constructor already accepts both rvalues and lvalues.

    Use std:forward(t) to forward the argument to other functions:

    template>
    var(T&& t) : m_something(std::forward(t)) {
        std::cout << "general value" << std::endl;
    }
    

    0 讨论(0)
提交回复
热议问题