Re: Громоздкость перегрузки конструктора копирования (и оператора присваивания)
От: T4r4sB Россия  
Дата: 04.11.15 15:24
Оценка: -3
Здравствуйте, _hum_, Вы писали:

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


Хехе, а вот в Аде там по умолчанию при копировании сначала делается простое побитовое копирование, потом для всех полей вызывается метод Adjust, а потом уже для самого класса вызывается метод Adjust. И да, писать почти одно и то же два раза (я про конструктор копирования и оператор =) в ней не надо,
Но это же противоречит принципу "не платить за то, что не заказывал", хотя экономия тут полторы спички.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[3]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: T4r4sB Россия  
Дата: 04.11.15 18:17
Оценка: -2 :)
Здравствуйте, _hum_, Вы писали:

__>да, но, если я правильно понял, все равно приходится ручками работать — перечислять все нужные поля в макросе адаптации


Подожди ещё лет 10, и дохлый страус наконец-то добавит рефлексию времени компиляции, и потом ещё 5, и она появится в Студии, и ещё 5, и новая Студия перестанет глючить.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[7]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: T4r4sB Россия  
Дата: 04.11.15 19:31
Оценка: +1
Здравствуйте, _hum_, Вы писали:

__>а кто гарантирует, что компилятор выравнивание для obj внутри CheckAlign и для obj самого по себе делает одинаково?


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

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


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


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


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

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

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

Ситуации, когда инициализация одних членов класса завязана на другие члены класса, у нас встречается редко. Пусть тот кто так написал сам и страдает
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;
Громоздкость перегрузки конструктора копирования (и оператора присваивания)
От: _hum_ Беларусь  
Дата: 04.11.15 14:00
Оценка:
Появились ли к настоящему моменту какие-нибудь эффективные способы написания перегрузок для соответствующих методов, позволяющие сократить до минимума тупое перечисление наподобие
m_field_val = Instance.m_field_val;


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

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

На всякий случай — у меня внутри класса гетерогенный контейнер (контейнер указателей на базовый класс, от которого наследуются разные классы объектов). Соответственно, именно для него приходится ручками писать копирование (а создавать отдельный копируемый класс для него как-то лень).
Re: Громоздкость перегрузки конструктора копирования (и оператора присваивания)
От: Warturtle  
Дата: 04.11.15 14:54
Оценка:
Здравствуйте, _hum_, Вы писали:

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

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


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


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


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

Можно сделать такое с помощью boost::fusion::for_each, предварительно адаптировав класс макросом вроде BOOST_FUSION_ADAPT_STRUCT. Например нужно сделать некоторые покомпонентные операции с большой структурою:
BOOST_FUSION_ADAPT_STRUCT(
    CHARFORMAT2,
    (DWORD,        dwMask)
    (DWORD,        dwEffects)
    (LONG,        yHeight)
    (LONG,        yOffset)
    (COLORREF,    crTextColor)
    (BYTE,        bCharSet)
    (BYTE,        bPitchAndFamily)
    (WORD,        wWeight)
    (SHORT,        sSpacing)
    (COLORREF,    crBackColor)
    (LCID,        lcid)
    (SHORT,        sStyle)
    (WORD,        wKerning)
    (BYTE,        bUnderlineType)
    (BYTE,        bAnimation)
    (BYTE,        bRevAuthor)
);

inline bool operator <(CHARFORMAT2 const & a, CHARFORMAT2 const & b)
{
    return fusion::less< CHARFORMAT2, CHARFORMAT2 >(a, b);
}

inline bool operator ==(CHARFORMAT2 const & a, CHARFORMAT2 const & b)
{
    return fusion::equal_to< CHARFORMAT2, CHARFORMAT2 >(a, b);
}

struct SequenceHasher
{
    SequenceHasher(size_t & seed) : m_seed(seed)
    {
    }
    template< class MemberT >
    void operator ()(MemberT const & data) const
    {
        boost::hash_combine(m_seed, data);
    }
    template< class SeqT >
    static inline size_t Calculate(SeqT const & seq)
    {
        static size_t const s_seed = ::GetTickCount();
        size_t seed = s_seed;
        fusion::for_each(seq, SequenceHasher(seed));
        return seed;
    }
private:
    size_t & m_seed;
};

namespace boost
{
    inline size_t hash_value(CHARFORMAT2 const & seq)
    {
        return SequenceHasher::Calculate(seq);
    }
}
Re: Громоздкость перегрузки конструктора копирования (и оператора присваивания)
От: Vain Россия google.ru
Дата: 04.11.15 15:22
Оценка:
Здравствуйте, _hum_, Вы писали:

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

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

А почему бы все эти поля просто убрать в структуру без всяких перегрузок и использовать что-то вроде такого:
data = Instance.data

?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re: Громоздкость перегрузки конструктора копирования (и оператора присваивания)
От: B0FEE664  
Дата: 04.11.15 17:58
Оценка:
Здравствуйте, _hum_, Вы писали:

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


Давно существует:
MyClass& MyClass::operator=(const MyClass& rObj)
{
    if( this != &rObj )
    {
       this->~MyClass();
       new (this) MyClass(rObj);
    }
    return *this;
}

но я почему-то страшусь таких конструкций.
И каждый день — без права на ошибку...
Re[2]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: T4r4sB Россия  
Дата: 04.11.15 18:15
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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


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


BFE>Давно существует:


ТС не то спрашивал.
Но я так и делаю, как ты написал.
Конструктор копирования должен быть ноэксепт для этого, конечно.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[2]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 18:15
Оценка:
Здравствуйте, Warturtle, Вы писали:

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


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

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


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


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


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

W>Можно сделать такое с помощью boost::fusion::for_each, предварительно адаптировав класс макросом вроде BOOST_FUSION_ADAPT_STRUCT. Например нужно сделать некоторые покомпонентные операции с большой структурою:
W>
W>BOOST_FUSION_ADAPT_STRUCT(
W>    CHARFORMAT2,
W>    (DWORD,        dwMask)
W>    (DWORD,        dwEffects)
W>    (LONG,        yHeight)
W>    (LONG,        yOffset)
W>    (COLORREF,    crTextColor)
W>    (BYTE,        bCharSet)
W>    (BYTE,        bPitchAndFamily)
W>    (WORD,        wWeight)
W>    (SHORT,        sSpacing)
W>    (COLORREF,    crBackColor)
W>    (LCID,        lcid)
W>    (SHORT,        sStyle)
W>    (WORD,        wKerning)
W>    (BYTE,        bUnderlineType)
W>    (BYTE,        bAnimation)
W>    (BYTE,        bRevAuthor)
W>);

W>inline bool operator <(CHARFORMAT2 const & a, CHARFORMAT2 const & b)
W>{
W>    return fusion::less< CHARFORMAT2, CHARFORMAT2 >(a, b);
W>}

W>inline bool operator ==(CHARFORMAT2 const & a, CHARFORMAT2 const & b)
W>{
W>    return fusion::equal_to< CHARFORMAT2, CHARFORMAT2 >(a, b);
W>}

W>struct SequenceHasher
W>{
W>    SequenceHasher(size_t & seed) : m_seed(seed)
W>    {
W>    }
W>    template< class MemberT >
W>    void operator ()(MemberT const & data) const
W>    {
W>        boost::hash_combine(m_seed, data);
W>    }
W>    template< class SeqT >
W>    static inline size_t Calculate(SeqT const & seq)
W>    {
W>        static size_t const s_seed = ::GetTickCount();
W>        size_t seed = s_seed;
W>        fusion::for_each(seq, SequenceHasher(seed));
W>        return seed;
W>    }
W>private:
W>    size_t & m_seed;
W>};

W>namespace boost
W>{
W>    inline size_t hash_value(CHARFORMAT2 const & seq)
W>    {
W>        return SequenceHasher::Calculate(seq);
W>    }
W>}
W>


да, но, если я правильно понял, все равно приходится ручками работать — перечислять все нужные поля в макросе адаптации
Re[2]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 18:21
Оценка:
Здравствуйте, Vain, Вы писали:

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


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

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

V>А почему бы все эти поля просто убрать в структуру без всяких перегрузок и использовать что-то вроде такого:
V>
V>data = Instance.data
V>

V>?
потому что, во-первых, это техническая структура, а во-вторых, если поля связаны между собою (например, объект одного поля имеет ссылки на объект другого поля за пределами data), то все еще больше усложнится. уж лучше тогда обернуть указатели в какие-нибудь смарт-поинтеры, которые автоматически при копировании клонируют свои объекты (кстати, а такого плана умные указатели вообще существуют, например, в том же бусте?).
Re[2]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 18:28
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


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


TB>Хехе, а вот в Аде там по умолчанию при копировании сначала делается простое побитовое копирование, потом для всех полей вызывается метод Adjust, а потом уже для самого класса вызывается метод Adjust.


во-во. что-то похожее хотелось бы организовать


TB> И да, писать почти одно и то же два раза (я про конструктор копирования и оператор =) в ней не надо,


так в с++ тоже во многих случаях (хотя и не всегда) копирование можно через присваивание определить:
CopyCtr(const CopyCtr& Inst)
{
   operator=(Inst);
}
Re[2]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 18:35
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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


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


BFE>Давно существует:

BFE>
BFE>MyClass& MyClass::operator=(const MyClass& rObj)
BFE>{
BFE>    if( this != &rObj )
BFE>    {
       this->>~MyClass();
BFE>       new (this) MyClass(rObj);
BFE>    }
BFE>    return *this;
BFE>}
BFE>

BFE>но я почему-то страшусь таких конструкций.

да, это немного не то — это как определить присваивание через конструктор копирования

кста, давече по поводу placement new натолкнулся на строгое предупреждение — мол, вам никто не гарантирует, что объект будет размещен именно с начала указателя на буфер. при размещении могут еще учитываться всякие выравнивания и проч.
потому я бы тоже побоялся такое использовать.
Re[3]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: T4r4sB Россия  
Дата: 04.11.15 18:36
Оценка:
Здравствуйте, _hum_, Вы писали:

__>так в с++ тоже во многих случаях (хотя и не всегда) копирование можно через присваивание определить:

__>
__>CopyCtr(const CopyCtr& Inst)
__>{
__>   operator=(Inst);
__>}
__>


Ты, наверное, хотел сказать так:

MyClass (const MyClass & other) : MyClass () // сначала надо таки инициализировать как-то
{
   operator=(other);
}
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[3]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: T4r4sB Россия  
Дата: 04.11.15 18:37
Оценка:
Здравствуйте, _hum_, Вы писали:
__>кста, давече по поводу placement new натолкнулся на строгое предупреждение — мол, вам никто не гарантирует, что объект будет размещен именно с начала указателя на буфер. при размещении могут еще учитываться всякие выравнивания и проч.
__>потому я бы тоже побоялся такое использовать.

Ну дык нефиг невыровненные указатели использовать.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[4]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 18:39
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


__>>да, но, если я правильно понял, все равно приходится ручками работать — перечислять все нужные поля в макросе адаптации


TB>Подожди ещё лет 10, и дохлый страус наконец-то добавит рефлексию времени компиляции, и потом ещё 5, и она появится в Студии, и ещё 5, и новая Студия перестанет глючить.


а в новом стандарте ничего по этому поводу не придумали? я слышал, там какие-то новшества вводили, связанные с дефолтными конструкторами и операторами присваивания. вот и надеялся, что может, и эту проблему разрулили.
Re[4]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 18:42
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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

__>>кста, давече по поводу placement new натолкнулся на строгое предупреждение — мол, вам никто не гарантирует, что объект будет размещен именно с начала указателя на буфер. при размещении могут еще учитываться всякие выравнивания и проч.
__>>потому я бы тоже побоялся такое использовать.

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


извиняюсь, а как в с++ можно удостовериться, что они выровнены нужным образом?
и еще, это единственное условие, или еще какие-то есть на корректность использования placement new?
Re[4]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 18:46
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


__>>так в с++ тоже во многих случаях (хотя и не всегда) копирование можно через присваивание определить:

__>>
__>>CopyCtr(const CopyCtr& Inst)
__>>{
__>>   operator=(Inst);
__>>}
__>>


TB>Ты, наверное, хотел сказать так:


TB>
TB>MyClass (const MyClass & other) : MyClass () // сначала надо таки инициализировать как-то
TB>{
TB>   operator=(other);
TB>}
TB>


зачем? присваивание и есть инициализация.

п.с. и вообще код
MyClass (const MyClass & other) : MyClass ()

разве пройдет?
Re[3]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: B0FEE664  
Дата: 04.11.15 18:47
Оценка:
Здравствуйте, _hum_, Вы писали:

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

__>да, это немного не то — это как определить присваивание через конструктор копирования

А, чёрт! Дак это, делегирующие конструкторы вам в помощь.
И каждый день — без права на ошибку...
Re[5]: Громоздкость перегрузки конструктора копирования (и о
От: B0FEE664  
Дата: 04.11.15 19:02
Оценка:
Здравствуйте, _hum_, Вы писали:

__>п.с. и вообще код

__>
__>MyClass (const MyClass & other) : MyClass ()
__>

__>разве пройдет?

Да. Это нововведение С++11. см. здесь
И каждый день — без права на ошибку...
Отредактировано 04.11.2015 19:11 B0FEE664 . Предыдущая версия .
Re[5]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: T4r4sB Россия  
Дата: 04.11.15 19:06
Оценка:
Здравствуйте, _hum_, Вы писали:

__>извиняюсь, а как в с++ можно удостовериться, что они выровнены нужным образом?


Ну можно завести структуру CheckAlign{ char c; MyClass obj; }, тогда sizeof(CheckAlign)-sizeof(MyClass) будет выравниванием, осталось проверить, что значение указателя делится на это выравнивание.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[5]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: T4r4sB Россия  
Дата: 04.11.15 19:10
Оценка:
Здравствуйте, _hum_, Вы писали:

__>зачем? присваивание и есть инициализация.


Затем, что присваивание не инициализация. Присваивание ещё и смотрит на то, что было в объекте до этого. Например, в умном указателе, такой утрированный пример:

clever_ptr& operator = (const clever_ptr& other)
{
  if (!m_ptr) // опа опа
    m_ptr = new T(*other.m_ptr);
  else
    *m_ptr = *other.m_ptr;
}


Поэтому очень важно, чтобы перед вызовом = объект находился в самосогласованном состоянии. Вызов пустого конструктора это и делает.

__>п.с. и вообще код

__>
__>MyClass (const MyClass & other) : MyClass ()
__>

__>разве пройдет?

Это делегирующие конструкторы. В ++03 нет, не пройдёт.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[4]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: B0FEE664  
Дата: 04.11.15 19:10
Оценка:
Здравствуйте, T4r4sB, Вы писали:

__>>кста, давече по поводу placement new натолкнулся на строгое предупреждение — мол, вам никто не гарантирует, что объект будет размещен именно с начала указателя на буфер. при размещении могут еще учитываться всякие выравнивания и проч.

__>>потому я бы тоже побоялся такое использовать.

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


А разве this может быть неправильно выровнен ?
И каждый день — без права на ошибку...
Re[5]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: T4r4sB Россия  
Дата: 04.11.15 19:12
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>А разве this может быть неправильно выровнен ?


reinterpret_cast<MyClass*>(size_t(1))->DoSome();
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[4]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 19:12
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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


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

__>>да, это немного не то — это как определить присваивание через конструктор копирования

BFE>А, чёрт! Дак это, делегирующие конструкторы вам в помощь.


вроде, не поможет, ибо непонятно, как вызвать дефолтный конструктор. запись наподобие
СopyCtr(const СopyCtr& Inst): СopyCtr(Inst)default
{
   //<particular reinitialization>
}

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

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


__>>извиняюсь, а как в с++ можно удостовериться, что они выровнены нужным образом?


TB>Ну можно завести структуру CheckAlign{ char c; MyClass obj; }, тогда sizeof(CheckAlign)-sizeof(MyClass) будет выравниванием, осталось проверить, что значение указателя делится на это выравнивание.

а кто гарантирует, что компилятор выравнивание для obj внутри CheckAlign и для obj самого по себе делает одинаково?
Re[6]: Громоздкость перегрузки конструктора копирования (и о
От: _hum_ Беларусь  
Дата: 04.11.15 19:36
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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


__>>п.с. и вообще код

__>>
__>>MyClass (const MyClass & other) : MyClass ()
__>>

__>>разве пройдет?

BFE>Да. Это нововведение С++11. см. здесь


аа, это, типа, делегирующий конструктор.
так а все-таки, он нужен (по-хорошему, должен применяться) при определении конструктора копирования через присваивание или не обязательно?
Re[3]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: Vain Россия google.ru
Дата: 04.11.15 19:46
Оценка:
Здравствуйте, _hum_, Вы писали:

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

тогда непонятно зачем вообще эти смарт поинтеры держать, а не положить сам объект в класс по значению а не ссылке/указателю.
Если они не копируемые, то вам и такой смарт поинтер ничем не поможет, т.к. опять не будет компилироваться из-за запрета на копирование. А если объект клонируемый, то обычно делают отдельную функцию создания/копирования и тогда не понятно как такой смартпоинтер должен быть генерализован, потому-что как правило функция клонирования уже использует смарт поинтер для возврата объекта. Проще тогда просто создавать класс объекта+смарт поинтер вокруг него с блекджеком и ...
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[7]: Громоздкость перегрузки конструктора копирования (и о
От: T4r4sB Россия  
Дата: 04.11.15 19:50
Оценка:
Здравствуйте, _hum_, Вы писали:


__>аа, это, типа, делегирующий конструктор.

__>так а все-таки, он нужен (по-хорошему, должен применяться) при определении конструктора копирования через присваивание или не обязательно?

Можно без него, в ++03 можно так:
void Init ()
{
  m_ptr = NULL;
}

MyClass () 
{ 
  Init ();
}

MyClass& operator = (const MyClass& other)
{
  //...
}


MyClass (const MyClass& other)
{
  Init();
  operator = (other);
}
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[6]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 19:58
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


__>>зачем? присваивание и есть инициализация.


TB>Затем, что присваивание не инициализация. Присваивание ещё и смотрит на то, что было в объекте до этого. Например, в умном указателе, такой утрированный пример:


TB>
TB>clever_ptr& operator = (const clever_ptr& other)
TB>{
TB>  if (!m_ptr) // опа опа
TB>    m_ptr = new T(*other.m_ptr);
TB>  else
TB>    *m_ptr = *other.m_ptr;
TB>}


TB>Поэтому очень важно, чтобы перед вызовом = объект находился в самосогласованном состоянии. Вызов пустого конструктора это и делает.


ну, в общем случае, наверное, да, согласен, что лучше все-таки его предварительно инициализировать, а потом уже делать присваивание.
Re[4]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 20:08
Оценка:
Здравствуйте, Vain, Вы писали:

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


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

V>тогда непонятно зачем вообще эти смарт поинтеры держать, а не положить сам объект в класс по значению а не ссылке/указателю.

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

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


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


чего ж запрета то? я же не про unique_ptr вел речь, а про некий обобщенный смарт-поинтер, который умеет копироваться, и при копировании копирует еще и объект, на который указывает образец.
Re: Громоздкость перегрузки конструктора копирования (и оператора присваивания)
От: Константин Россия  
Дата: 04.11.15 20:08
Оценка:
Здравствуйте, _hum_, Вы писали:

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

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

Думаю, что создать отдельный класс для копируемых полей будет самым практичным. Да там и писать будет всего ничего.
Re[5]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: Vain Россия google.ru
Дата: 04.11.15 20:12
Оценка:
Здравствуйте, _hum_, Вы писали:

__>чего ж запрета то? я же не про unique_ptr вел речь, а про некий обобщенный смарт-поинтер, который умеет копироваться, и при копировании копирует еще и объект, на который указывает образец.

при клонировании конструктор копирования обычно прикрывают.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[8]: Громоздкость перегрузки конструктора копирования (и о
От: _hum_ Беларусь  
Дата: 04.11.15 20:17
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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



__>>аа, это, типа, делегирующий конструктор.

__>>так а все-таки, он нужен (по-хорошему, должен применяться) при определении конструктора копирования через присваивание или не обязательно?

TB>Можно без него, в ++03 можно так:

TB>
TB>void Init ()
TB>{
TB>  m_ptr = NULL;
TB>}

TB>MyClass () 
TB>{ 
TB>  Init ();
TB>}

TB>MyClass& operator = (const MyClass& other)
TB>{
TB>  //...
TB>}


TB>MyClass (const MyClass& other)
TB>{
TB>  Init();
TB>  operator = (other);
TB>}
TB>


угу. токо так не всегда удобно делать, если, например, код инициализации должен быть гарантированно вызван только один раз — при конструировании объекта.
Re[9]: Громоздкость перегрузки конструктора копирования (и о
От: T4r4sB Россия  
Дата: 04.11.15 20:19
Оценка:
Здравствуйте, _hum_, Вы писали:

__>угу. токо так не всегда удобно делать, если, например, код инициализации должен быть гарантированно вызван только один раз — при конструировании объекта.


А где он у меня вызывается два раза?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[5]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: Vain Россия google.ru
Дата: 04.11.15 20:22
Оценка:
Здравствуйте, _hum_, Вы писали:

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

__>>На всякий случай — у меня внутри класса гетерогенный контейнер (контейнер указателей на базовый класс, от которого наследуются разные классы объектов). Соответственно, именно для него приходится ручками писать копирование (а создавать отдельный копируемый класс для него как-то лень).
ну положите оффсеты относительно базы, зачем там именно поинтеры на this? чтобы осложнить себе жизнь?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[6]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 20:27
Оценка:
Здравствуйте, Vain, Вы писали:

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


__>>чего ж запрета то? я же не про unique_ptr вел речь, а про некий обобщенный смарт-поинтер, который умеет копироваться, и при копировании копирует еще и объект, на который указывает образец.

V>при клонировании конструктор копирования обычно прикрывают.

может, я неудачно термин употребил, но под клонированием я понимал создание точной копии объекта. так что смысла прятать конструктор копирования как бы нет.

грубо горя, ситуация типа такой:

enum KINDs{kind_a, kind_b};

class CAbstactItem
{
    virtual KINDs kind_of()= 0;
};

class CItemA : public CAbstactItem{ //<implementation>};
class CItemB : public CAbstactItem{ //<implementation>};



class CFoo
{
   //<100500 копируемых полей>


   std::vector<CAbstactItem*> m_ItemsStock;
};



и нужно организовать возможность копирования объектов класса CFoo при условии, что CItemA и CItemB сами по себе copyable
Re[6]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 20:31
Оценка:
Здравствуйте, Vain, Вы писали:

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


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

__>>>На всякий случай — у меня внутри класса гетерогенный контейнер (контейнер указателей на базовый класс, от которого наследуются разные классы объектов). Соответственно, именно для него приходится ручками писать копирование (а создавать отдельный копируемый класс для него как-то лень).
V>ну положите оффсеты относительно базы, зачем там именно поинтеры на this? чтобы осложнить себе жизнь?
вы о чем. какие оффсеты?
Re[10]: Громоздкость перегрузки конструктора копирования (и о
От: _hum_ Беларусь  
Дата: 04.11.15 20:34
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


__>>угу. токо так не всегда удобно делать, если, например, код инициализации должен быть гарантированно вызван только один раз — при конструировании объекта.


TB>А где он у меня вызывается два раза?


у вас нигде. но никто не запрещает это сделать в любом месте и по многу раз
Re[3]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: _hum_ Беларусь  
Дата: 04.11.15 20:37
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


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


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


BFE>>Давно существует:


TB>ТС не то спрашивал.

TB>Но я так и делаю, как ты написал.
TB>Конструктор копирования должен быть ноэксепт для этого, конечно.

а где вам такое приходится делать? не проще ли все-таки конструктор копирования через оператор присваивания определять?
Re[7]: Громоздкость перегрузки конструктора копирования (и оператора присваивани
От: Vain Россия google.ru
Дата: 04.11.15 20:41
Оценка:
Здравствуйте, _hum_, Вы писали:

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

__>>>>На всякий случай — у меня внутри класса гетерогенный контейнер (контейнер указателей на базовый класс, от которого наследуются разные классы объектов). Соответственно, именно для него приходится ручками писать копирование (а создавать отдельный копируемый класс для него как-то лень).
V>>ну положите оффсеты относительно базы, зачем там именно поинтеры на this? чтобы осложнить себе жизнь?
__>вы о чем. какие оффсеты?
у вас m_ItemsStock куда указывает, как выделены объекты в нём?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
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_, Вы писали:

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


Не знаю, может и проще. Мне сама идея не нравится тем, что предъявляет к объекту дополнительное требование: "нулевое состояние".
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
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>Видимо он может быть по-разному выровнен, к примеру, на стеке и в хипе. На хипе обычно делают выравнивание с запасом. На стеке, только до необходимой величины.


Ну и что плохого этот запас сделает? Плацемент по-другому сработает?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
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[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[2]: Любопытно,наверно,такая конструкция будет работать внутри наследованного
От: johny5 Новая Зеландия
Дата: 07.11.15 12:39
Оценка:
<>
Re[2]: Их писать не нужно
От: _hum_ Беларусь  
Дата: 07.11.15 18:16
Оценка:
Здравствуйте, johny5, Вы писали:


J>На самом деле их писать не нужно — только ошибок понаделаете и отключите заодно генерацию move конструкторов.

J>Члены класса должны сами знать как себя копировать. Тогда автоматически сгенерированные конструкторы окажутся подходящими.

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


J>--


J>Если совсем никак не обойтись, можно покурить такую тему (C++11):

J>
J>class Copy
J>{
J>public:
J>  Copy() {}

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

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

J>protected:
J>  void operator=(const other& it) = default;
J>


это почти что нужно, за исключение одного НО — как в вашем варианте определить еще и свой оператор присваивания (ведь если задача требует определения своего конструктора копирования, то нельзя оставлять "нэйтивный" оператор присваивания)?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.