Re[2]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 20:55
Оценка:
Здравствуйте, Константин, Вы писали:

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


__>>Например, если в классе очень много копируемых полей, и очень мало указателей (unique owners), то такое перечисление выглядит очень дико (к тому же вероятность пропустить, не дописать и т.п. многократно увеличивается).

__>>Может, появилась какая-нить возможность принудительно вызывать конструктор копирования по умолчанию внутри перегрузки конструктора копирования?
__>>...а создавать отдельный копируемый класс для него как-то лень...

К>Думаю, что создать отдельный класс для копируемых полей будет самым практичным. Да там и писать будет всего ничего.


уверены? а как насчет, например, воспроизведения такой последовательности инициализации:


class CFoo
{
   const CA m_A;//copyable

   const CB m_B;//non-copyable

   const CC m_C;//copyable

   CFoo():m_A(100), m_B(m_A), m_C(m_B){}
};
Re[8]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 21:01
Оценка:
Здравствуйте, Vain, Вы писали:

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


__>>>>я же писал в самом начале:

__>>>>>На всякий случай — у меня внутри класса гетерогенный контейнер (контейнер указателей на базовый класс, от которого наследуются разные классы объектов). Соответственно, именно для него приходится ручками писать копирование (а создавать отдельный копируемый класс для него как-то лень).
V>>>ну положите оффсеты относительно базы, зачем там именно поинтеры на this? чтобы осложнить себе жизнь?
__>>вы о чем. какие оффсеты?
V>у вас m_ItemsStock куда указывает, как выделены объекты в нём?

int i;
std::cin>>i;

const bool b = (0 == i % 2);

m_ItemsStock[0] = b ? (new CItemA()) : (new CItemB());
m_ItemsStock[1] = b ? (new CItemB()) : (new CItemA());;
Re[4]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: T4r4sB Россия  
Дата: 04.11.15 21:20
Оценка:
Здравствуйте, _hum_, Вы писали:

__>а где вам такое приходится делать? не проще ли все-таки конструктор копирования через оператор присваивания определять?


Не знаю, может и проще. Мне сама идея не нравится тем, что предъявляет к объекту дополнительное требование: "нулевое состояние".
Re[5]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 21:30
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


__>>а где вам такое приходится делать? не проще ли все-таки конструктор копирования через оператор присваивания определять?


TB>Не знаю, может и проще. Мне сама идея не нравится тем, что предъявляет к объекту дополнительное требование: "нулевое состояние".


так вы же сами предложили способ, как от этого избавиться — использовать делегированный конструктор. это уж лучше, чем требования всяких выровненностей.
Re[9]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: Vain Россия google.ru
Дата: 04.11.15 23:25
Оценка:
Здравствуйте, _hum_, Вы писали:

__>
__>int i;
__>std::cin>>i;

__>const bool b = (0 == i % 2);

__>m_ItemsStock[0] = b ? (new CItemA()) : (new CItemB());
__>m_ItemsStock[1] = b ? (new CItemB()) : (new CItemA());;
__>

а эти классы обязательно через new создавать?
std::vector<boost::any> m_ItemsStock;
b ? m_ItemsStock.push_back(CItemA()) : m_ItemsStock.push_back(CItemB());
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[3]: Громоздкость перегрузки конструктора копирования (и о
От: Константин Россия  
Дата: 05.11.15 00:26
Оценка:
Здравствуйте, _hum_, Вы писали:

__>>>Например, если в классе очень много копируемых полей, и очень мало указателей (unique owners), то такое перечисление выглядит очень дико (к тому же вероятность пропустить, не дописать и т.п. многократно увеличивается).

__>>>Может, появилась какая-нить возможность принудительно вызывать конструктор копирования по умолчанию внутри перегрузки конструктора копирования?
__>>>...а создавать отдельный копируемый класс для него как-то лень...
К>>Думаю, что создать отдельный класс для копируемых полей будет самым практичным. Да там и писать будет всего ничего.

__>уверены? а как насчет, например, воспроизведения такой последовательности инициализации:


__>
__>class CFoo {
__> // мышка за кошку
__> // кошка за Жучку
__> // Жучка за внучку
__> // внучка за бабку
__> // бабка за дедку
__> // дедка за репку
__>};
__>


Может лучше привести пример кода близкий к реальному? Или у вас в коде на самом деле всё так плохо, как в примере?
Отредактировано 05.11.2015 0:44 Константин . Предыдущая версия .
Re[10]: Громоздкость перегрузки конструктора копирования (и оператора присваиван
От: _hum_ Беларусь  
Дата: 05.11.15 07:43
Оценка:
Здравствуйте, Vain, Вы писали:

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


__>>
__>>int i;
__>>std::cin>>i;

__>>const bool b = (0 == i % 2);

__>>m_ItemsStock[0] = b ? (new CItemA()) : (new CItemB());
__>>m_ItemsStock[1] = b ? (new CItemB()) : (new CItemA());;
__>>

V>а эти классы обязательно через new создавать?
V>
V>std::vector<boost::any> m_ItemsStock;
V>b ? m_ItemsStock.push_back(CItemA()) : m_ItemsStock.push_back(CItemB());
V>

интересная штука этот паттерн "variant" (кстати, некое подобие смарт-поинтера, о котором я выше вел речь). но ведь тогда, чтобы вызвать виртуальную функцию, придется писать вместо
m_ItemsStock[i]->virt_fun();

что-то наподобие
((CAbstactItem&)(m_ItemsStock[i])).virt_fun();

или того хуже — switch-case. нет?
Re[4]: Громоздкость перегрузки конструктора копирования (и о
От: _hum_ Беларусь  
Дата: 05.11.15 08:15
Оценка:
Здравствуйте, Константин, Вы писали:

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


__>>>>Например, если в классе очень много копируемых полей, и очень мало указателей (unique owners), то такое перечисление выглядит очень дико (к тому же вероятность пропустить, не дописать и т.п. многократно увеличивается).

__>>>>Может, появилась какая-нить возможность принудительно вызывать конструктор копирования по умолчанию внутри перегрузки конструктора копирования?
__>>>>...а создавать отдельный копируемый класс для него как-то лень...
К>>>Думаю, что создать отдельный класс для копируемых полей будет самым практичным. Да там и писать будет всего ничего.

__>>уверены? а как насчет, например, воспроизведения такой последовательности инициализации:


__>>
__>>class CFoo {
__>> // мышка за кошку
__>> // кошка за Жучку
__>> // Жучка за внучку
__>> // внучка за бабку
__>> // бабка за дедку
__>> // дедка за репку
__>>};
__>>


К>Может лучше привести пример кода близкий к реальному? Или у вас в коде на самом деле всё так плохо, как в примере?


я лишь хотел показать, что есть подводные камни, и не все так просто, как кажется.
а ситуация, когда объекты взаимодействуют между собой (а значит, должны инициализироваться в строгой последовательности), по-моему, сплошь и рядом.
Re[11]: Громоздкость перегрузки конструктора копирования (и оператора присваиван
От: Vain Россия google.ru
Дата: 05.11.15 08:24
Оценка:
Здравствуйте, _hum_, Вы писали:

__>но ведь тогда, чтобы вызвать виртуальную функцию, придется писать вместо

__>
__>m_ItemsStock[i]->virt_fun();
__>

__>что-то наподобие
__>
__>((CAbstactItem&)(m_ItemsStock[i])).virt_fun();
__>

__>или того хуже — switch-case. нет?
да, тип не известен, придётся делать boost::any_cast, да ещё ловить исключения
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[5]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: Vain Россия google.ru
Дата: 05.11.15 08:27
Оценка:
Здравствуйте, B0FEE664, Вы писали:

TB>>Ну дык нефиг невыровненные указатели использовать.

BFE>А разве this может быть неправильно выровнен ?
Видимо он может быть по-разному выровнен, к примеру, на стеке и в хипе. На хипе обычно делают выравнивание с запасом. На стеке, только до необходимой величины.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re: Громоздкость перегрузки конструктора копирования (и оператора присваивания)
От: CEMb  
Дата: 05.11.15 08:52
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Появились ли к настоящему моменту какие-нибудь эффективные способы написания перегрузок для соответствующих методов, позволяющие сократить до минимума тупое перечисление наподобие

__>
__>m_field_val = Instance.m_field_val; 
__>


[злая_шутка]
memcpy(this, &Instance, sizeof (*this));
[/злая_шутка]

я за идею создания класса-шаблона автокопируемых полей. С++ тем и хорош: 1. там нет лишнего. 2. любое нужное можно сделать.
Re[6]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: T4r4sB Россия  
Дата: 05.11.15 09:32
Оценка:
Здравствуйте, Vain, Вы писали:

V>Видимо он может быть по-разному выровнен, к примеру, на стеке и в хипе. На хипе обычно делают выравнивание с запасом. На стеке, только до необходимой величины.


Ну и что плохого этот запас сделает? Плацемент по-другому сработает?
Re[12]: Громоздкость перегрузки конструктора копирования (и оператора присваиван
От: _hum_ Беларусь  
Дата: 05.11.15 09:48
Оценка:
Здравствуйте, Vain, Вы писали:

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


__>>но ведь тогда, чтобы вызвать виртуальную функцию, придется писать вместо

__>>
__>>m_ItemsStock[i]->virt_fun();
__>>

__>>что-то наподобие
__>>
__>>((CAbstactItem&)(m_ItemsStock[i])).virt_fun();
__>>

__>>или того хуже — switch-case. нет?
V>да, тип не известен, придётся делать boost::any_cast, да ещё ловить исключения

тогда это все же не очень красивое решение
Re[2]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 05.11.15 09:57
Оценка:
Здравствуйте, CEMb, Вы писали:

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


__>>Появились ли к настоящему моменту какие-нибудь эффективные способы написания перегрузок для соответствующих методов, позволяющие сократить до минимума тупое перечисление наподобие

__>>
__>>m_field_val = Instance.m_field_val; 
__>>


CEM>[злая_шутка]

CEM>
CEM>memcpy(this, &Instance, sizeof (*this));
CEM>
[/злая_шутка]


CEM>я за идею создания класса-шаблона автокопируемых полей. С++ тем и хорош: 1. там нет лишнего. 2. любое нужное можно сделать.


что за идея-то? создание отденьного класса,в который помещаются все копируемые поля? так уже выше обсуждалось, почему это не всегда возможно. или имелась в виду идея обертки каждого некопируемого класса в делающий его копируемым класс?
Re[3]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: CEMb  
Дата: 05.11.15 10:06
Оценка:
Здравствуйте, _hum_, Вы писали:

__>или имелась в виду идея обертки каждого некопируемого класса в делающий его копируемым класс?

ага. Не для каждого, а просто дефайн-шаблон написать. Ну и класс-контейнер таких итемов должен иметь функционал для работы с такими штуками.
Хотя, на вскидку, решение простое не получится... Но задачка интересная Т.е. при объявлении, как-то надо суметь их или внести в список. Или в операторе копирования уметь их находить в классе и вызывать их оператор копирования.
Re[5]: Громоздкость перегрузки конструктора копирования (и о
От: Константин Россия  
Дата: 05.11.15 10:42
Оценка: :)
Здравствуйте, _hum_, Вы писали:

__>>>уверены? а как насчет, например, воспроизведения такой последовательности инициализации:


__>>>
__>>>class CFoo {
__>>> // мышка за кошку
__>>> // ...
__>>> // дедка за репку
__>>>};
__>>>


К>>Может лучше привести пример кода близкий к реальному? Или у вас в коде на самом деле всё так плохо, как в примере?


__>я лишь хотел показать, что есть подводные камни, и не все так просто, как кажется.

__>а ситуация, когда объекты взаимодействуют между собой (а значит, должны инициализироваться в строгой последовательности), по-моему, сплошь и рядом.

Я исходил для типичного для нашего кода случая, когда члены класса инициализируются независимо.

Ситуации, когда инициализация одних членов класса завязана на другие члены класса, у нас встречается редко. Пусть тот кто так написал сам и страдает
Re[3]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: Warturtle  
Дата: 05.11.15 13:14
Оценка:
Здравствуйте, _hum_, Вы писали:

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


W>>...

__>да, но, если я правильно понял, все равно приходится ручками работать — перечислять все нужные поля в макросе адаптации
Ну если класс свой, а не из заголовков какой-то библиотеки, то можно перечислить поля лишь однажды.
Re: Громоздкость перегрузки конструктора копирования (и оператора присваивания)
От: PM  
Дата: 05.11.15 21:13
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Появились ли к настоящему моменту какие-нибудь эффективные способы написания перегрузок для соответствующих методов, позволяющие сократить до минимума тупое перечисление наподобие

__>
__>m_field_val = Instance.m_field_val; 
__>


Это невозможно, пока в языке нет поддержки рефлексии времени компиляции. Есть только костыль в виде boost.fusion

__>Например, если в классе очень много копируемых полей, и очень мало указателей (unique owners), то такое перечисление выглядит очень дико (к тому же вероятность пропустить, не дописать и т.п. многократно увеличивается).


Наверняка эти unique_ptr там не спроста. Меня в таком случае обычно устраивает некопируемость класса (в C++11 он может быть при этом перемещаемым)

__>Может, появилась какая-нить возможность принудительно вызывать конструктор копирования по умолчанию внутри перегрузки конструктора копирования?


__>На всякий случай — у меня внутри класса гетерогенный контейнер (контейнер указателей на базовый класс, от которого наследуются разные классы объектов). Соответственно, именно для него приходится ручками писать копирование (а создавать отдельный копируемый класс для него как-то лень).


Посмотрите доклад http://2012.cppnow.org/session/value-semantics-and-concepts-based-polymorphism/ может быть появятся идеи как это сделать в вашем случае.

В boost есть библиотека гетерогенных контейнеров ptr_container

Ещё один способ иногда пригодный для плоских иерархий — использовать variant и variant visitor для создания полиморфного интерфейса

struct Dog { void woof(); };
struct Cat { void mew(); };

using Animal = variant<Dog, Cat>;

void say(Animal& animal)
{
    struct visitor
    {
        void operator()(Dog& dog) { dog.woof(); }
        void operator()(Cat& cat) { cat.mew(); }
    };

    animal.visit(visitor());
}

std::vector<Animal> animals { Cat(), Dog() };

say(animals[0]);
say(animals[1]);
Re[2]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: red75  
Дата: 06.11.15 12:47
Оценка:
Здравствуйте, PM, Вы писали:

PM>Ещё один способ иногда пригодный для плоских иерархий — использовать variant и variant visitor для создания полиморфного интерфейса


Класс. Это так теперь паттерн-матчинг называется?
Есть ещё https://github.com/solodon4/Mach7 макросами, темплейтами и какой-то матерью сделан почти вменяемый pattern-matching.

// Lambda calculator
struct Term       { virtual ~Term() {}     };
struct Var : Term { std::string name;      };
struct Abs : Term { Var&  var;  Term& body;};
struct App : Term { Term& func; Term& arg; };

Term* eval(Term* t)
{
    var<const Var&> v; 
    var<const Term&> b,a;

    Match(*t)
    {
      Case(C<Var>())               return &match0;
      Case(C<Abs>())               return &match0;
      Case(C<App>(C<Abs>(v,b),a))  return eval(subs(b,v,a));
      Otherwise() cerr << "error"; return nullptr ;
    } 
    EndMatch
}
Re: Их писать не нужно
От: johny5 Новая Зеландия
Дата: 07.11.15 12:36
Оценка: +1
На самом деле их писать не нужно — только ошибок понаделаете и отключите заодно генерацию move конструкторов.
Члены класса должны сами знать как себя копировать. Тогда автоматически сгенерированные конструкторы окажутся подходящими.

Перегружать копирование редко нужно только для утилитарных классов типа shared_ptr.

--

Если совсем никак не обойтись, можно покурить такую тему (C++11):
class Copy
{
public:
  Copy() {}

  Copy(const Copy& it) : Copy()
  {
    *this = it;

    .. add here your specific 'copy adjust' code ..
  }

protected:
  void operator=(const other& it) = default;
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.