move argument
От: Logot Украина  
Дата: 16.11.15 13:45
Оценка:
Привет
Почему так не работает?
struct movable
{
};

class one
{
public:
    one(movable&& m)
        : _m(m)
    {}

    movable    _m;
};

class creator
{
public:
    template<typename S, typename ... Args>
    static S* create(Args ... args)
    {
        return new one(args ...);
    }
};

int main(int argc, char** argv)
{
    movable m;
    creator::create<one, movable&&>(std::forward<movable>(m));
    return 0;
}


1>probe.cpp(442): error C2664: 'one::one(const one &)' : cannot convert argument 1 from 'moveable' to 'moveable &&'


MS VS 2013
Как можно сделать, чтобы работало?
Re: move argument
От: Igore Россия  
Дата: 16.11.15 13:54
Оценка:
Здравствуйте, Logot, Вы писали:

L>MS VS 2013

L>Как можно сделать, чтобы работало?
Проверил на 2015
#include <utility>

struct movable
{
};

class one
{
public:
    one(movable&& m)
        : _m(m)
    {}

    movable    _m;
};

class creator
{
public:
    template<typename S, typename ... Args>
    static S* create(Args ... args)
    {
        return new one(std::move(args ...));
    }
};

int main(int , char** )
{
    movable m;
    creator::create<one, movable&&>(std::forward<movable>(m));
    return 0;
}
Отредактировано 16.11.2015 13:58 Igore . Предыдущая версия .
Re[2]: move argument
От: Logot Украина  
Дата: 16.11.15 14:14
Оценка:
Здравствуйте, Igore, Вы писали:

I>Здравствуйте, Logot, Вы писали:


L>>MS VS 2013

L>>Как можно сделать, чтобы работало?
I>Проверил на 2015
I>
I>#include <utility>

I>struct movable
I>{
I>};

I>class one
I>{
I>public:
I>    one(movable&& m)
I>        : _m(m)
I>    {}

I>    movable    _m;
I>};

I>class creator
I>{
I>public:
I>    template<typename S, typename ... Args>
I>    static S* create(Args ... args)
I>    {
I>        return new one(std::move(args ...));
I>    }
I>};

I>int main(int , char** )
I>{
I>    movable m;
I>    creator::create<one, movable&&>(std::forward<movable>(m));
I>    return 0;
I>}
I>


но на самом деле у меня one принимает несколько параметров
Re[3]: move argument
От: Igore Россия  
Дата: 16.11.15 14:30
Оценка: 2 (1)
Здравствуйте, Logot, Вы писали:

L>но на самом деле у меня one принимает несколько параметров

Тогда так
#include <utility>

struct movable
{
};
struct notMovable
{
};

class one
{
public:
    one(movable&& m,notMovable nm)
        : _m(m), _nm(nm)
    {}

    movable    _m;
    notMovable _nm;
};

class creator
{
public:
    template<typename S, typename ... Args>
    static S* create(Args ... args)
    {
        return new one(std::forward<Args>(args)...);
    }
};

int main(int , char** )
{
    movable m;
    notMovable nm;
    creator::create<one, movable&&,notMovable>(std::forward<movable>(m),nm);
    return 0;
}
Re[4]: move argument
От: _niko_ Россия  
Дата: 16.11.15 16:01
Оценка: 3 (1)
Здравствуйте, Igore, Вы писали:

На самом деле у Вас тоже не совсем корректно )

#include <utility>

struct movable
{
    movable() = default;
    movable(movable&&) = default;
    movable& operator=(movable&&) = default;
 
    movable(const movable&) = delete;
    movable& operator=(const movable&) = delete;
};
struct notMovable
{
    notMovable() = default;
    notMovable(const notMovable&) = default;
    notMovable& operator=(const notMovable&) = default;
 
    notMovable(notMovable&&) = delete;
    notMovable& operator=(notMovable&&) = delete;
};

class one
{
public:
    one(movable&& m,notMovable nm)
        // Хоть переменная m и попала сюда через перемещение здесь она уже имеет имя/адрес т.е. она как бы lvalue
        // поэтому для последующего перемещения её используем std::forward
        : _m(std::forward<movable>(m)), _nm(nm)
    {}

    movable    _m;
    notMovable _nm;
};

class creator
{
public:
    template<typename S, typename ... Args>
    static S* create(Args&& ... args) // Здесь необходимо указать семантику перемещения, иначе все в функцию попадает через конструктор копирования
    {
        return new one(std::forward<Args>(args)...);
    }
};

int main(int , char** )
{
    movable m;
    notMovable nm;
    creator::create<one>(std::move(m),nm); // В параметрах шаблона не нужно указывать перемещение, т.к. переменная m находится на стеке (lvalue) её перемещаем явно
    return 0;
}


Вот теперь переменная m только перемещается!
Отредактировано 16.11.2015 16:16 _niko_ . Предыдущая версия .
Re[5]: move argument
От: uzhas Ниоткуда  
Дата: 17.11.15 07:26
Оценка: 4 (1)
Здравствуйте, _niko_, Вы писали:

__>На самом деле у Вас тоже не совсем корректно )


__>[ccode]

__> one(movable&& m,notMovable nm)
__> // Хоть переменная m и попала сюда через перемещение здесь она уже имеет имя/адрес т.е. она как бы lvalue
__> // поэтому для последующего перемещения её используем std::forward
__> : _m(std::forward<movable>(m)), _nm(nm)
__> {}

здесь нужно использовать std::move, а не std::forward
std::forward используют для deduced types (чаще всего для "универсальных ссылок"), см. perfect forwarding
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.