Re: Конструктор копирования из шаблонного типа
От: jazzer Россия Skype: enerjazzer
Дата: 17.08.09 08:22
Оценка: 9 (2) +1
Здравствуйте, minorlogic, Вы писали:

M>Конструктор копирования из шаблонного типа



M>В библиотеке где тип "притворяется" вещественный числом, есть очень интересный конструктор.



M>
M>template <typename T>
M>class FTypeName // STACK-BASED
M>{
M>    T m_val;
M>    T m_diff[N];
M>    bool m_depend;
M>public:
M>         .....

M>    template <class U> /*explicit*/ FTypeName(const U& val):m_val(val),m_depend(false)
M>    {
M>    }
M>         .....

M>


M>У меня вопрос с коллегам , зачем такой конструктор мог понадобиться ?

M>Спасибо!

как вариант — решили сэкономить на создании копии (копия будет создана только один раз в m_val(val), а если написать конструктор от Т, то будет две копии, хотя я на 90% уверен, что эта лишняя копия будет изничтожена компилятором).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: Конструктор копирования из шаблонного типа
От: jazzer Россия Skype: enerjazzer
Дата: 17.08.09 18:05
Оценка: 12 (1)
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Здравствуйте, jazzer, Вы писали:


J>>Здравствуйте, Юрий Жмеренецкий, Вы писали:


J>>>>Тогда при копировании получится U = FTypeName, т.е. полное совпадение сигнатуры, при которой выигрывает нешаблонная функция.

ЮЖ>>>Это справедливо для функций, в случае с конструкторами поведение другое:
ЮЖ>>>

12.8/3
ЮЖ>>>A member function template is never instantiated to perform the copy of a class object to an object of its class type.


J>>Имхо, это относится только к случаю X(X), а не к X(const X&), просто потому что конструктор вида X(X) запрещен из-за бесконечной рекурсии и попытка инстанцирования немедленно привела бы к ошибке, а к конструторам из ссылки это не относится, тут достаточно простого правила про преимущество нешаблонной функции.


ЮЖ>Недостаточно. Т.е. недостаточно если рассматривать преимущество нешаблонной функции как единственный фактор, на основании которого происходит выбор:


пример поскипан, у меня 3 часа ночи, я в такое время думать не могу, завтра подумаю.
Единственное соображение — то, что ты цитируешь, вырвано из абзаца, в котором говорится про конструктор вида Х(Х), посему я настаиваю, что и цитата относится только к этому виду конструктора.
Если твой пример показывает что-то другое, то должно быть какое-то еще объяснение либо это просто дефект стандарта (опять же, в 3 часа ночи я в список дефектов не полезу), но не процитированный текст.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Конструктор копирования из шаблонного типа
От: Николай Ивченков  
Дата: 17.08.09 12:22
Оценка: 4 (1)
jazzer:

S>>на каком компиляторе/уровне оптимизации будет выкинуто создание копии в конструкторе holder_1?


J>у меня есть только гцц 3.4.6, он не выкидывает.

J>Но я не вижу причин, по которым бы временный объект, который там создается при вызове конструктора holder_1, не мог бы быть выкинут и s не могла бы быть инициализирована напрямую, учитывая то, что весь код компилятору доступен.

Данный случай не подпадает под условия 12.8/15, поэтому исполнение действий, осуществляемых в копирующем конструкторе, может быть устранено только при условии, что observable behavior будет таким же, как если бы ничего не устранялось, и компилятор умеет это обнаруживать. (В случаях же, подпадающих под условия 12.8/15, устранение вызова копирующего конструктора может на вполне законных основаниях менять observable behavior — следовательно, такой вид оптимизации производить гораздо проще)
Конструктор копирования из шаблонного типа
От: minorlogic Украина  
Дата: 17.08.09 08:03
Оценка:
Конструктор копирования из шаблонного типа


В библиотеке где тип "притворяется" вещественный числом, есть очень интересный конструктор.


template <typename T>
class FTypeName // STACK-BASED
{
    T m_val;
    T m_diff[N];
    bool m_depend;
public:
         .....

    template <class U> /*explicit*/ FTypeName(const U& val):m_val(val),m_depend(false)
    {
    }
         .....


У меня вопрос с коллегам , зачем такой конструктор мог понадобиться ?
Спасибо!
Ищу работу, 3D, SLAM, computer graphics/vision.
Re: Конструктор копирования из шаблонного типа
От: Bell Россия  
Дата: 17.08.09 08:13
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Конструктор копирования из шаблонного типа



M>В библиотеке где тип "притворяется" вещественный числом, есть очень интересный конструктор.



M>
M>template <typename T>
M>class FTypeName // STACK-BASED
M>{
M>    T m_val;
M>    T m_diff[N];
M>    bool m_depend;
M>public:
M>         .....

M>    template <class U> /*explicit*/ FTypeName(const U& val):m_val(val),m_depend(false)
M>    {
M>    }
M>         .....

M>


M>У меня вопрос с коллегам , зачем такой конструктор мог понадобиться ?

M>Спасибо!


Это не конструктор копирования, это обычный конструктор, который позволяет создать объект типа FTypeName, используя инициализатор любого подходящего типа.
Любите книгу — источник знаний (с) М.Горький
Re[2]: Конструктор копирования из шаблонного типа
От: Wasilij  
Дата: 17.08.09 08:17
Оценка:
Здравствуйте, Bell, Вы писали:

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


M>>Конструктор копирования из шаблонного типа



M>>В библиотеке где тип "притворяется" вещественный числом, есть очень интересный конструктор.



M>>
M>>template <typename T>
M>>class FTypeName // STACK-BASED
M>>{
M>>    T m_val;
M>>    T m_diff[N];
M>>    bool m_depend;
M>>public:
M>>         .....

M>>    template <class U> /*explicit*/ FTypeName(const U& val):m_val(val),m_depend(false)
M>>    {
M>>    }
M>>         .....

M>>


M>>У меня вопрос с коллегам , зачем такой конструктор мог понадобиться ?

M>>Спасибо!


B>Это не конструктор копирования, это обычный конструктор, который позволяет создать объект типа FTypeName, используя инициализатор любого подходящего типа.


А чем он отличается от:


template <typename T>
class FTypeName // STACK-BASED
{
    T m_val;
    T m_diff[N];
    bool m_depend;
public:
    FTypeName(const typename T& val):m_val(val),m_depend(false)
    {
    }
};
Re[3]: Конструктор копирования из шаблонного типа
От: Bell Россия  
Дата: 17.08.09 08:36
Оценка:
Здравствуйте, Wasilij, Вы писали:

W>А чем он отличается от:


W>
W>template <typename T>
W>class FTypeName // STACK-BASED
W>{
W>    T m_val;
W>    T m_diff[N];
W>    bool m_depend;
W>public:
W>    FTypeName(const typename T& val):m_val(val),m_depend(false)
W>    {
W>    }
W>};
W>


Jazzer ниже привел одно отличие.
Еще можно предположить, что авторы хотели, чтобы преобразование U -> T выполнялось "внутри" класса FTypeName. Вот пример для иллюстрации:

template <class T>
class Test2
{
   T t_;
public:
   template<class U>
   Test2(const U& u) : t_(u) {}
};

class Test
{
   template <class T> friend class Test2;
private:
   operator int() const { return 1; }
};

int main()
{
  Test t;
  Test2<double> t2(t);
}

Любите книгу — источник знаний (с) М.Горький
Re[2]: Конструктор копирования из шаблонного типа
От: minorlogic Украина  
Дата: 17.08.09 08:41
Оценка:
Sorry, ошибся.

Просто конструктор из другого типа.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: Конструктор копирования из шаблонного типа
От: sokel Россия  
Дата: 17.08.09 08:49
Оценка:
Здравствуйте, jazzer, Вы писали:

J>как вариант — решили сэкономить на создании копии (копия будет создана только один раз в m_val(val), а если написать конструктор от Т, то будет две копии, хотя я на 90% уверен, что эта лишняя копия будет изничтожена компилятором).


Только вот 90% уверенности — это многовато аналогично insert(make_pair/value_type):
#include <stdio.h>

struct string
{
    const char* str;
    string(const char* str) : str(str) { puts("constructor"); }
    string(const string& other) : str(other.str) { puts("copy constructor");  }
};

struct holder_1 { string s; holder_1(const string& s) : s(s) {} };
struct holder_2 { string s; template<typename T> holder_2(const T& s) : s(s) {} };

int main()
{
    puts("holder 1:");
    holder_1("some string");
    puts("holder 2:");
    holder_2("some string");
    return 0;
};

на каком компиляторе/уровне оптимизации будет выкинуто создание копии в конструкторе holder_1?
Re[2]: Конструктор копирования из шаблонного типа
От: jazzer Россия Skype: enerjazzer
Дата: 17.08.09 08:52
Оценка:
Здравствуйте, jazzer, Вы писали:

Кстати, к вопросу о сабже — этот конструктор не является конструктором копирования, если для этого класса компилятор способен сгенерить такой конструктор (а судя по описанию, он способен это сделать).
т.е. когда компилятор сгенерит копиктор, в классе получится вот что:
template <class U> FTypeName(const U& val); // шаблонный
FTypeName(const FTypeName& val); // сгенерен компилятором, не шаблонный!

Тогда при копировании получится U = FTypeName, т.е. полное совпадение сигнатуры, при которой выигрывает нешаблонная функция.
Т.е. если это было попыткой убить одним выстрелом двух зайцев (конструктор из другого типа и копиктор), то это не сработает, будет вызвано то, что молча сгенерил компилятор.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Конструктор копирования из шаблонного типа
От: Юрий Жмеренецкий ICQ 380412032
Дата: 17.08.09 09:21
Оценка:
Здравствуйте, jazzer, Вы писали:

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


J>Кстати, к вопросу о сабже — этот конструктор не является конструктором копирования, если для этого класса компилятор способен сгенерить такой конструктор (а судя по описанию, он способен это сделать).

J>т.е. когда компилятор сгенерит копиктор, в классе получится вот что:
J>
J>template <class U> FTypeName(const U& val); // шаблонный
J>FTypeName(const FTypeName& val); // сгенерен компилятором, не шаблонный!
J>

J>Тогда при копировании получится U = FTypeName, т.е. полное совпадение сигнатуры, при которой выигрывает нешаблонная функция.
Это справедливо для функций, в случае с конструкторами поведение другое:

12.8/3
A member function template is never instantiated to perform the copy of a class object to an object of its class type.

Re[4]: Конструктор копирования из шаблонного типа
От: jazzer Россия Skype: enerjazzer
Дата: 17.08.09 09:37
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

J>>Тогда при копировании получится U = FTypeName, т.е. полное совпадение сигнатуры, при которой выигрывает нешаблонная функция.

ЮЖ>Это справедливо для функций, в случае с конструкторами поведение другое:
ЮЖ>

12.8/3
ЮЖ>A member function template is never instantiated to perform the copy of a class object to an object of its class type.


Имхо, это относится только к случаю X(X), а не к X(const X&), просто потому что конструктор вида X(X) запрещен из-за бесконечной рекурсии и попытка инстанцирования немедленно привела бы к ошибке, а к конструторам из ссылки это не относится, тут достаточно простого правила про преимущество нешаблонной функции.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Конструктор копирования из шаблонного типа
От: jazzer Россия Skype: enerjazzer
Дата: 17.08.09 11:34
Оценка:
Здравствуйте, sokel, Вы писали:

S>на каком компиляторе/уровне оптимизации будет выкинуто создание копии в конструкторе holder_1?


у меня есть только гцц 3.4.6, он не выкидывает.
Но я не вижу причин, по которым бы временный объект, который там создается при вызове конструктора holder_1, не мог бы быть выкинут и s не могла бы быть инициализирована напрямую, учитывая то, что весь код компилятору доступен.
Можно, разве что, порассуждать про ОДР, но, имхо, ОДР применима только к коду, который написан программером, а не к оптимизированному коду, который генерится компилятором каждый раз по-своему, в зависимости от локальной ситуации...
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Конструктор копирования из шаблонного типа
От: Николай Ивченков  
Дата: 17.08.09 12:21
Оценка:
Юрий Жмеренецкий:

ЮЖ>

12.8/3
A member function template is never instantiated to perform the copy of a class object to an object of its class type.

IMHO, это очередной дефект стандарта. Из 8.5/14/4/2, 13.3.1.3 и правил разрешения перегрузки следует, что при инициализации объекта классового типа выражением такого же типа шаблонный конструктор в некоторых случаях может иметь преимущество перед копирующим конструктором. Например, такая программа

#include <iostream>

struct X
{
    X() {}
    template <class T>
        X(T &)
    {
        std::cout << "template ctor" << std::endl;
    }
private:
    X(X const &);
};

struct Y
{
    Y() {}
    template <class T>
        Y(T const &)
    {
        std::cout << "template ctor" << std::endl;
    }
private:
    explicit Y(Y const &);    
};

int main()
{
    X x;
    Y y;
    
    X x1 = x;
    X x2(x);
    Y y1 = y;
}

должна вывести

template ctor
template ctor
template ctor

Случай, когда могла бы возникнуть бесконечная рекурсия, было бы уместно описать в 14-ом разделе как одну из причин неудачной дедукции типа (такая специализация автоматически исключалась бы из множества candidate functions), а в 12.8/3 нужно уточнить вид первого параметра шаблонного конструктора. А то получается непонятно что.
Re[5]: Конструктор копирования из шаблонного типа
От: Юрий Жмеренецкий ICQ 380412032
Дата: 17.08.09 13:34
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Юрий Жмеренецкий, Вы писали:


J>>>Тогда при копировании получится U = FTypeName, т.е. полное совпадение сигнатуры, при которой выигрывает нешаблонная функция.

ЮЖ>>Это справедливо для функций, в случае с конструкторами поведение другое:
ЮЖ>>

12.8/3
ЮЖ>>A member function template is never instantiated to perform the copy of a class object to an object of its class type.


J>Имхо, это относится только к случаю X(X), а не к X(const X&), просто потому что конструктор вида X(X) запрещен из-за бесконечной рекурсии и попытка инстанцирования немедленно привела бы к ошибке, а к конструторам из ссылки это не относится, тут достаточно простого правила про преимущество нешаблонной функции.


Недостаточно. Т.е. недостаточно если рассматривать преимущество нешаблонной функции как единственный фактор, на основании которого происходит выбор:
struct A
{
  A();

  A(A&);

  template<class T>
  A(const T&)
  {}
};

struct B : A
{
  B();
};

int main()
{
  B b;
  B b1 = b; // error
}
Re[5]: Конструктор копирования из шаблонного типа
От: Юрий Жмеренецкий ICQ 380412032
Дата: 17.08.09 14:37
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

НИ>Юрий Жмеренецкий:


ЮЖ>>

12.8/3
НИ>A member function template is never instantiated to perform the copy of a class object to an object of its class type.

НИ>IMHO, это очередной дефект стандарта. Из 8.5/14/4/2, 13.3.1.3 и правил разрешения перегрузки следует, что при инициализации объекта классового типа выражением такого же типа шаблонный конструктор в некоторых случаях может иметь преимущество перед копирующим конструктором.

Но ведь это инициализация, а не копирование... При copy-initialization рассматриваются все converting constructors, в число которых входит и non-explicit copy constructor (12.3.1/3). При direct — те же, включая explicit версии. Какой конкретно конструктор будет выбран — зависит от ситуации.

В местах где может быть использован только copy constructor — будет использоваться именно он.

НИ>Случай, когда могла бы возникнуть бесконечная рекурсия, было бы уместно описать в 14-ом разделе как одну из причин неудачной дедукции типа.

НИ>а в 12.8/3 нужно уточнить вид первого параметра шаблонного конструктора. А то получается непонятно что.
Почему не понятно что? Первое предложение не относится к function template. Даже если не принимать во внимание это предложение, все равно я не вижу способа вызвать рекурсию с использованим template converting constructor'а. Попытки сделать это намеренно приведут к UB согласно 14.7.1/14, только к самому конструктору это никак не относится.
Re[5]: Конструктор копирования из шаблонного типа
От: jazzer Россия Skype: enerjazzer
Дата: 17.08.09 16:35
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

НИ>jazzer:


S>>>на каком компиляторе/уровне оптимизации будет выкинуто создание копии в конструкторе holder_1?


J>>у меня есть только гцц 3.4.6, он не выкидывает.

J>>Но я не вижу причин, по которым бы временный объект, который там создается при вызове конструктора holder_1, не мог бы быть выкинут и s не могла бы быть инициализирована напрямую, учитывая то, что весь код компилятору доступен.

НИ>Данный случай не подпадает под условия 12.8/15, поэтому исполнение действий, осуществляемых в копирующем конструкторе, может быть устранено только при условии, что observable behavior будет таким же, как если бы ничего не устранялось, и компилятор умеет это обнаруживать. (В случаях же, подпадающих под условия 12.8/15, устранение вызова копирующего конструктора может на вполне законных основаниях менять observable behavior — следовательно, такой вид оптимизации производить гораздо проще)


Может быть, может быть, я не смотрел стандарт, времени нету сейчас совсем.
Просто суть этой оптимизации в том, чтоб разрешить избавляться от временных объектов там, где они не нужны.
Имхо, это как раз такой случай (по крайней мере, я навскидку не вижу принципиальных препятствий), но он вполне может быть и не прописан в стандарте явно.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: Конструктор копирования из шаблонного типа
От: Николай Ивченков  
Дата: 17.08.09 17:00
Оценка:
Юрий Жмеренецкий:

ЮЖ>Но ведь это инициализация, а не копирование...


А что такое копирование? В 12.8/1 сказано:

A class object can be copied in two ways, by initialization (12.1, 8.5), including for function argument passing (5.2.2) and for function value return (6.6.3), and by assignment (5.17). Conceptually, these two operations are implemented by a copy constructor (12.1) and copy assignment operator (13.5.3).

но здесь "copied" курсивом не выделено. Надо ли считать этот абзац определением копирования, неясно. Только ли копирующий конструктор может осуществлять копирование в виде инициализации? В сноске 106, например, говорится:

Template constructors participate in overload resolution with other constructors, including copy constructors, and a template constructor may be used to copy an object if it provides a better match than other constructors.

В отношении неявного определения копирующего конструктора, вроде бы, прямо сказано про использование копирующего конструктора подобъекта (12.8/8):

The implicitly-defined copy constructor for class X performs a memberwise copy of its subobjects. The order of copying is the same as the order of initialization of bases and members in a user-defined constructor (see 12.6.2). Each subobject is copied in the manner appropriate to its type:
— if the subobject is of class type, the copy constructor for the class is used;
— if the subobject is an array, each element is copied, in the manner appropriate to the element type;
— if the subobject is of scalar type, the built-in assignment operator is used.

Однако, следующий пример

#include <iostream>

struct X
{
    X() {}
    template <class T>
        explicit X(T &)
    {
        std::cout << "template ctor" << std::endl;
    }
private:
    X(X const volatile &);
};

struct Y
{
    X x;
};

int main()
{
    Y y1;
    Y y2(y1);
}

компилируют VC++, GNU C++ и даже Comeau, т.е. они по сути выполняют почленную direct-initialization.

НИ>>Случай, когда могла бы возникнуть бесконечная рекурсия, было бы уместно описать в 14-ом разделе как одну из причин неудачной дедукции типа.

НИ>>а в 12.8/3 нужно уточнить вид первого параметра шаблонного конструктора. А то получается непонятно что.
ЮЖ>Почему не понятно что?

Рассмотрим такой пример:

struct X
{
    template <class T>
        X(T)
    {
    }
};

int main()
{
    volatile X x1(1);
    X x2(x1);
}

Как здесь формируется set of candidate functions при инициализации x1? Шаблон функции-конструктора не может быть candidate function, кандидатом может быть специализация шаблона. Чтобы получить специализацию, нужно произвести дедукцию шаблонного аргумента для шаблонного параметра T и затем подставить выведенный тип на место T. Полученная специализация T(int) и будет одной из candidate functions (второй будет копирующий конструктор). А как формируется set of candidate functions при инициализации x2? Где в стандарте можно увидеть внятное объяснение?

ЮЖ>Первое предложение не относится к function template.


О каком первом предложении идёт речь?
Re[7]: Конструктор копирования из шаблонного типа
От: Юрий Жмеренецкий ICQ 380412032
Дата: 17.08.09 23:40
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

НИ>Юрий Жмеренецкий:


ЮЖ>>Но ведь это инициализация, а не копирование...

НИ>А что такое копирование?

Возможное действие выполняемое при инициализации =)

НИ>В 12.8/1 сказано:

НИ>

A class object can be copied in two ways, by initialization (12.1, 8.5), including for function argument passing (5.2.2) and for function value return (6.6.3), and by assignment (5.17). Conceptually, these two operations are implemented by a copy constructor (12.1) and copy assignment operator (13.5.3).

НИ>но здесь "copied" курсивом не выделено. Надо ли считать этот абзац определением копирования, неясно. Только ли копирующий конструктор может осуществлять копирование в виде инициализации?

DR#331: Allowed copy constructor signatures:

Change 12.1 [class.ctor] paragraph 10 from

A copy constructor for a class X is a constructor with a first parameter of type X& or of type const X&. [Note: see 12.8 [class.copy] for more information on copy constructors. ]

to :

A copy constructor (12.8 [class.copy]) is used to copy objects of class type.


НИ>В отношении неявного определения копирующего конструктора, вроде бы, прямо сказано про использование копирующего конструктора подобъекта (12.8/8):

НИ>

The implicitly-defined copy constructor for class X performs a memberwise copy of its subobjects. The order of copying is the same as the order of initialization of bases and members in a user-defined constructor (see 12.6.2). Each subobject is copied in the manner appropriate to its type:
НИ>— if the subobject is of class type, the copy constructor for the class is used;


В core language active issue #535 "Copy construction without a copy constructor" предлагают заменить эту строку следующей:

if the subobject is of class type, direct-initialization (8.5 [dcl.init]) is performed

Там же предлагается еще 13 подобных исправлений.

ЮЖ>>Почему не понятно что?

НИ>Рассмотрим такой пример:

НИ>
struct X
НИ>{
НИ>    template <class T>
НИ>        X(T)
НИ>    {
НИ>    }
НИ>};

НИ>int main()
НИ>{
НИ>    volatile X x1(1);
НИ>    X x2(x1);
НИ>}

НИ>Как здесь формируется set of candidate functions при инициализации x1?
Так же как и при использовании функций. 13.3.1/7:

In each case where a candidate is a function template, candidate function template specializations are generated using template argument deduction (14.8.3, 14.8.2). Those candidates are then handled as candidate functions in the usual way


НИ>А как формируется set of candidate functions при инициализации x2? Где в стандарте можно увидеть внятное объяснение?


Что-то вроде такого:
13.3.1.3/1:

For direct-initialization, the candidate functions are all the constructors of the class of the object being initialized.


Варианты:
1) X(const X&)
2) X(X)

Аргумент — volatile lvalue

13.3.1/2
For the purposes of overload resolution, both static and non-static member functions have an implicit object parameter, but constructors do not.

Итого:

1) volatile X -> const X&
2) volatile X -> X

Оба варианта в конечном итоге не могут быть использованы из-за C.1.8:

The implicitly-declared copy constructor and implicitly-declared copy assignment operator cannot make a copy of a volatile lvalue

Re[7]: Конструктор копирования из шаблонного типа
От: Юрий Жмеренецкий ICQ 380412032
Дата: 18.08.09 00:06
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Если твой пример показывает что-то другое, то должно быть какое-то еще объяснение либо это просто дефект стандарта (опять же, в 3 часа ночи я в список дефектов не полезу), но не процитированный текст.


Пример можно считать неактуальным. Некоторые объяснения есть в ответе Николаю.
Re[6]: Конструктор копирования из шаблонного типа
От: ilvi Россия  
Дата: 18.08.09 02:00
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>
struct A
ЮЖ>{
ЮЖ>  A();

ЮЖ>  A(A&);

ЮЖ>  template<class T>
ЮЖ>  A(const T&)
ЮЖ>  {}
ЮЖ>};

ЮЖ>struct B : A
ЮЖ>{
ЮЖ>  B();
ЮЖ>};

ЮЖ>int main()
ЮЖ>{
ЮЖ>  B b;
ЮЖ>  B b1 = b; // error
ЮЖ>}


Можно уточнить, какого типа ошибка подразумевалась в строке B b1 = b; — логическая или синтаксическая?
Re[7]: Конструктор копирования из шаблонного типа
От: Юрий Жмеренецкий ICQ 380412032
Дата: 18.08.09 02:59
Оценка:
Здравствуйте, ilvi, Вы писали:
...
I>Можно уточнить, какого типа ошибка подразумевалась в строке B b1 = b; — логическая или синтаксическая?
Пример не показывает то что задумывалось, там моя 'ошибка'.
Re[7]: Конструктор копирования из шаблонного типа
От: Юрий Жмеренецкий ICQ 380412032
Дата: 18.08.09 04:07
Оценка:
Здравствуйте, jazzer, Вы писали:
...
J>Единственное соображение — то, что ты цитируешь, вырвано из абзаца, в котором говорится про конструктор вида Х(Х), посему я настаиваю, что и цитата относится только к этому виду конструктора.

Да, похоже ты прав, цитата относится к конкретному виду. Тот смысл, который я на нее возлагал размазался по другим частям стандарта. Хотя после чтения дефектов складывается ощущение, что с терминологий в этой области стандарта бардак.
Re[6]: Конструктор копирования из шаблонного типа
От: jazzer Россия Skype: enerjazzer
Дата: 18.08.09 06:01
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Может быть, может быть, я не смотрел стандарт, времени нету сейчас совсем.

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

Посмотрел стандарт.
То, что нечто не прописано явно, большой роли не играет: достаточно сравнить С++03 с его двумя пунктами и С++0х с четырьмя (это без ссылок на значения), так что дописать отсутствующие пункты не проблема.

Но там еще есть очень неприятный запрет:

...when a temporary class object that has not been bound to a reference...

и этот запрет убивает всё: если у нас ссылка (как раз наш случай), то временный объект никогда не будет изничтожен.

Пока что мне этот запрет кажется слишком сильным, поскольку закрывает возможности для таких оптимизаций, мне надо подумать, почему он такой есть (т.е. какой осмысленный код сломается, если этот запрет снять полностью или частично).
Потому что в приведенном примере с конструктором я не вижу проблем.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: Конструктор копирования из шаблонного типа
От: sokel Россия  
Дата: 18.08.09 06:06
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

НИ>Данный случай не подпадает под условия 12.8/15, поэтому исполнение действий, осуществляемых в копирующем конструкторе, может быть устранено только при условии, что observable behavior будет таким же, как если бы ничего не устранялось, и компилятор умеет это обнаруживать. (В случаях же, подпадающих под условия 12.8/15, устранение вызова копирующего конструктора может на вполне законных основаниях менять observable behavior — следовательно, такой вид оптимизации производить гораздо проще)


А почему не попадает под условия 12.8/15? Разве это не этот случай:

When certain criteria are met, an implementation is allowed to omit the copy construction of a class object,
even if the copy constructor and/or destructor for the object have side effects.
...
— when a temporary class object that has not been bound to a reference (12.2) would be copied to a class
object with the same cv-unqualified type, the copy operation can be omitted by constructing the temporary
object directly into the target of the omitted copy

Re[6]: Конструктор копирования из шаблонного типа
От: jazzer Россия Skype: enerjazzer
Дата: 18.08.09 09:11
Оценка:
Здравствуйте, sokel, Вы писали:

S>А почему не попадает под условия 12.8/15? Разве это не этот случай:

S>

S>When certain criteria are met, an implementation is allowed to omit the copy construction of a class object,
S>even if the copy constructor and/or destructor for the object have side effects.
S>...
S>— when a temporary class object that has not been bound to a reference (12.2) would be copied to a class
S>object with the same cv-unqualified type, the copy operation can be omitted by constructing the temporary
S>object directly into the target of the omitted copy


http://www.rsdn.ru/forum/cpp/3507040.1.aspx
Автор: jazzer
Дата: 18.08.09
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[8]: Конструктор копирования из шаблонного типа
От: Николай Ивченков  
Дата: 18.08.09 14:14
Оценка:
Юрий Жмеренецкий:

ЮЖ>В core language active issue #535 "Copy construction without a copy constructor" предлагают заменить эту строку следующей:


ЮЖ>

if the subobject is of class type, direct-initialization (8.5 [dcl.init]) is performed

ЮЖ>Там же предлагается еще 13 подобных исправлений.

Так что мы имеем насчёт "ЮЖ>>Но ведь это инициализация, а не копирование"? Копирование там или не копирование?

НИ>>А как формируется set of candidate functions при инициализации x2? Где в стандарте можно увидеть внятное объяснение?


ЮЖ>Что-то вроде такого:

ЮЖ>13.3.1.3/1:
ЮЖ>

For direct-initialization, the candidate functions are all the constructors of the class of the object being initialized.


ЮЖ>Варианты:

ЮЖ>1) X(const X&)
ЮЖ>2) X(X)

ЮЖ>Аргумент — volatile lvalue


ЮЖ>

13.3.1/2
ЮЖ>For the purposes of overload resolution, both static and non-static member functions have an implicit object parameter, but constructors do not.

ЮЖ>Итого:

ЮЖ>1) volatile X -> const X&

ЮЖ>2) volatile X -> X

ЮЖ>Оба варианта в конечном итоге не могут быть использованы из-за C.1.8:


ЮЖ>

The implicitly-declared copy constructor and implicitly-declared copy assignment operator cannot make a copy of a volatile lvalue


Пункт C.1.8 не является нормативным. Копирующий конструктор не является viable function в силу того, что тип const X не является reference-compatible с volatile X. А вот по каким правилам полученная специализация X(X) не является viable function, пока что неясно.
Re: Что поменяется если разкоментировать explicit?
От: minorlogic Украина  
Дата: 18.08.09 14:21
Оценка:
Что поменяется если разкоментировать explicit?
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[9]: Конструктор копирования из шаблонного типа
От: Юрий Жмеренецкий ICQ 380412032
Дата: 19.08.09 03:22
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

НИ>Так что мы имеем насчёт "ЮЖ>>Но ведь это инициализация, а не копирование"? Копирование там или не копирование?


12.1/2
A constructor is used to initialize objects of its class type.

Инициализация 'from a copy' выполняется с помощью copy ctor'ов. Вот это я называя 'копированием' (не рассматривая assignment). Так же, во всех местах где описываются возможные оптимизации связанные с copy elision, — везде фигурируют именно конструкторы копирования.

НИ>Пункт C.1.8 не является нормативным. Копирующий конструктор не является viable function в силу того, что тип const X не является reference-compatible с volatile X.

Разумеется C.1.8 не на пустом месте стоит.

НИ>А вот по каким правилам полученная специализация X(X) не является viable function, пока что неясно.

Так же как и в случае с обычными функциями. Преобразование volatile X -> X можно выполнить с помощью X:(const volatile& X) и введением временного объекта (это не приведет к рекурсии), но такого конструктора у нас нет. Причем для копирования временного объекта используются только конструкторы копирования — 12.2/4 (template ctor'ы не рассматриваются). Но если бы конструктор X:(const volatile& X) существовал, то был бы использован сразу.
Re[7]: Конструктор копирования из шаблонного типа
От: sokel Россия  
Дата: 19.08.09 08:11
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Пока что мне этот запрет кажется слишком сильным, поскольку закрывает возможности для таких оптимизаций, мне надо подумать, почему он такой есть (т.е. какой осмысленный код сломается, если этот запрет снять полностью или частично).

J>Потому что в приведенном примере с конструктором я не вижу проблем.

Я думаю, тут получаются сложности со временем жизни этого temporary object. То есть, в случае того же конструктора, компилятор должен дополнительно учесть что он нигде, кроме как в списке инициализации, не участвует. А это в стандарте уже сложнее формализовать.
Re[8]: Конструктор копирования из шаблонного типа
От: jazzer Россия Skype: enerjazzer
Дата: 19.08.09 08:42
Оценка:
Здравствуйте, sokel, Вы писали:

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


J>>Пока что мне этот запрет кажется слишком сильным, поскольку закрывает возможности для таких оптимизаций, мне надо подумать, почему он такой есть (т.е. какой осмысленный код сломается, если этот запрет снять полностью или частично).

J>>Потому что в приведенном примере с конструктором я не вижу проблем.

S>Я думаю, тут получаются сложности со временем жизни этого temporary object. То есть, в случае того же конструктора, компилятор должен дополнительно учесть что он нигде, кроме как в списке инициализации, не участвует. А это в стандарте уже сложнее формализовать.


формализовать как раз просто.
Если временный объект используется только для того, чтоб проинициализировать другой объект того же типа, то такой временный объект может быть изничтожен. И все. Это включает в себя и нынешние copy elision.
Если компилятор способен этот случай детектировать — все супер, пусть убивает нафиг.
Не способен — ну что ж, никто и не обещал, что оптимизация всегда будет работать.
Другое дело, если этот объект протаскивается через цепочку вызовов — тут надо подумать, можно ли сформулировать корректно.
Надо думать, придумывать разные хитрые примеры, когда хорошо изничтожать, а когда плохо, а у меня сейчас времени нету
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[10]: Конструктор копирования из шаблонного типа
От: Николай Ивченков  
Дата: 19.08.09 12:26
Оценка:
Юрий Жмеренецкий:

НИ>>Так что мы имеем насчёт "ЮЖ>>Но ведь это инициализация, а не копирование"? Копирование там или не копирование?


ЮЖ>

12.1/2
ЮЖ>A constructor is used to initialize objects of its class type.

ЮЖ>Инициализация 'from a copy' выполняется с помощью copy ctor'ов. Вот это я называя 'копированием' (не рассматривая assignment).

В данном случае меня интересует, что копированием называет стандарт. Судя по приведённым ссылкам, одними копирующими конструкторами здесь дело не ограничивается. Поэтому с замечанием "Но ведь это инициализация, а не копирование" я согласиться не могу.

НИ>>А вот по каким правилам полученная специализация X(X) не является viable function, пока что неясно.

ЮЖ>Так же как и в случае с обычными функциями. Преобразование volatile X -> X можно выполнить с помощью X:(const volatile& X) и введением временного объекта (это не приведет к рекурсии), но такого конструктора у нас нет.

Инициализацию аргумента специализации X(X) можно осуществить с помощью этой же самой специализации. Так что механизм исключения специализации X(X) из рассмотрения остаётся неясен. Такое исключение может произойти как на этапе формирования set of candidate functions, так и на этапе формирования set of viable functions. Ничего внятного по этому вопросу я в стандарте не вижу.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.