Class with template constructor, and copy and move constructor

This question is a continuation of this: Explicit specialized specialization of the template template template template The answers asked in another question are certainly correct, but it turned out that I didn’t quite ask what I wanted to ask, so here is a new question:

Consider the following code:

template<typename First, typename ... Rest> class var {
    public:

    var() {
        std::cout << "default" << std::endl;
    }

    var(const var& v) {
        std::cout << "copy" << std::endl;
    }

    var(var&& v) {
        std::cout << "move" << std::endl;
    }

    template<typename T>
    var(const T& t) {
        std::cout << "general lvalue" << std::endl;
    }


    template<typename T>
    var(T&& t) {
        std::cout << "general rvalue" << std::endl;
    }

};


int main()
{
    var<int> i0; // expect 'default' -> get 'default'

    var<int> i1(i0); // expect 'copy' -> get 'general rvalue'
    var<int> i2(std::move(i0)); // expect 'move' -> get 'move'

    std::string s("Hello");
    var<int> i3(s); // expect 'general lvalue' -> get 'general rvalue'
    var<int> i4(std::move(s)); // expect 'general rvalue' -> get 'general rvalue'
}

I wrote in the main function the constructors that I expect and want to be called and which of them are actually called. Here are my questions:

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

2) How to make a program call a copy and move the var constructor when it receives var and template constructors otherwise?

3) , , lvalues, rvalues ​​ , std:: forward - ?

+1
1

1) , , ?

:

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

var(T&&) T, var<int>&, .. :

var(var&);

, var(const var&), i0 .

:

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

s const, var(T&&) T, std::string&, :

var(std::string&);

non-const , :

var(const std::string&);

, var(T&&) " rvalue", T&& , lvalues.

. ++ 11.

2) var, var ?

, .

template<typename T>
  using Is_a_var = std::is_same<typename std::decay<T>::type, var>;

template<typename T>
  using Enable_if_not_a_var = typename std::enable_if<!Is_a_var<T>::value>::type;

template<typename T, typename Constraint = Enable_if_not_a_var<T>>
var(T&& t) {
    std::cout << "general value" << std::endl;
}

copy/move , , :

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

3) , , lvalues, rvalues ​​ , std:: forward - ?

. var(T&&) rvalues ​​ lvalues.

std:forward<T>(t) :

template<typename T, typename Constraint = Enable_if_not_a_var<T>>
var(T&& t) : m_something(std::forward<T>(t)) {
    std::cout << "general value" << std::endl;
}
+2

All Articles