2014-02-25 2 views
1

Этот вопрос является продолжением следующего: Explicit template specialization for templated constructor of templated class Ответы, заданные в другом вопросе, конечно же правильные, но оказалось, что я не совсем спрашивал, что хочу спросить - так вот новый вопрос:Класс с шаблоном конструктором, а также копировать и перемещать конструктор

Рассмотрим следующий код:

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' 
} 

я писал в главной функции, конструкторы я ожидаю и хочу назвать и какие из них на самом деле называется. Вот мои вопросы:

1) Можете ли вы объяснить, почему программа не ведет себя так, как я ожидал?

2) Как я могу заставить программу вызывать копию и перемещать конструктор var, когда он получает var и шаблонные конструкторы в противном случае?

3) И, наконец, я пытаюсь поместить два шаблонных конструктора в одну обработку как lvalues, так и rvalues ​​и перенаправлять их на другую функцию, используя std :: forward - как это могло бы выглядеть?

ответ

2

1) Можете ли вы объяснить, почему программа не ведет себя так, как я ожидал?

На этой линии:

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

var(T&&) конструктор реализованным с T замещенным var<int>&, т.е. производит конструктор с этой подписью:

var(var&); 

Это строи tor является лучшим совпадением, чем неявный конструктор копирования var(const var&), потому что i0 не является константой.

Аналогично для:

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

s является Неконстантным, поэтому var(T&&) конструктора создается с T замещенного std::string&, производя конструктор с подписью:

var(std::string&); 

Для неконстантного аргумента t шляпа конструктор лучше подходит, чем другой шаблон конструктора, который производит:

var(const std::string&); 

Вы должны понимать, что var(T&&) конструктор не «вообще Rvalue» конструктор, потому что T&& может соответствовать любому типу включая lvalues ​​.

Для получения более подробной информации см. Universal References in C++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; 
} 

Я хотел бы также добавить дефолтные копировать/перемещать конструкторы, чтобы быть ясны читателям вы хотите их:

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

3) И, наконец, я пытаюсь поставить два шаблонных конструктора в одну обработку как lvalues, так и rvalues ​​и перенаправление их на другую функцию с использованием std :: forward - как это могло бы выглядеть?

Нельзя. Конструктор var(T&&) уже принимает оба значения и 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; 
} 
+0

Большой и очень подробный ответ. Помог мне много! Благодаря! – mg84

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