L>Далее автор предлагает "написать определение переменной a".
Он же не требует использовать при этом именно этот конкретный конструктор — который недоступен для использования, согласно стандарту. Но можно воспользоваться другими конструторами — копирования и перемещения, которые определены неявно компилятором.
Не уверен на счет корректности автоинициализации, как здесь
, но, до тех пор, пока класс остается POD-типом, можно интерпретировать любой кусок памяти, достаточного размера, как объект данного типа и выполнить инициализацию копированием:
template <typename T>
using storage = std::array<unsigned char, sizeof(T)>;
str a = reinterpret_cast<const str&>(static_cast<const storage<str>&>(storage<str>()));
--
Не можешь достичь желаемого — пожелай достигнутого.
А что Вас смущает? Объект занят самокопированием. Синтаксически здесь всё корректно.
6.3.2 Point of declaration
1. The point of declaration for a name is immediately after its complete declarator (Clause 11) and before its
initializer (if any), except as noted below. [ Example:
unsigned char x = 12;
{ unsigned char x = x; }
Here the second x is initialized with its own (indeterminate) value. —end example ]
Здравствуйте, Croessmah, Вы писали:
C>А что Вас смущает? Объект занят самокопированием. Синтаксически здесь всё корректно.
Не знаю, не готов отстаивать свою позицию. Просто это рвет мои шаблоны. Как мне казалось, принимая ссылку на самого себя, конструктор копирования пытается использовать объект, время жизни которого еще не началось (время жизни объекта начинается после завершения работы конструктора, согласно стандарту). Я попробовал смоделировать ситуацию, когда это привело бы к каким-нибудь неприятностям. Но не тут-то было. Попробовал и так, и эдак — работает и не падает! Мне нужен таймаут, чтобы раобраться получше.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Croessmah, Вы писали:
C>>А что Вас смущает? Объект занят самокопированием. Синтаксически здесь всё корректно.
R>конструктор копирования пытается использовать объект, время жизни которого еще не началось (время жизни объекта начинается после завершения работы конструктора, согласно стандарту).
Тоже самое происходит и в Вашем коде. У Вас есть только буфер байт, в нем нет объекта типа str, т.е. Ваш код занимается тем же самым — копированием из объекта, время жизни которого еще не началось.
> Я попробовал смоделировать ситуацию, когда это привело бы к каким-нибудь неприятностям. Но не тут-то было. Попробовал и так, и эдак — работает и не падает!
Тип же не содержит каких-то сложных операций при конструировании.
Результат для типа, содержащего std::string есть здесь.
Может не воспроизводится, т.к. код содержит неопределенное поведение.
Здравствуйте, Croessmah, Вы писали:
C>А что Вас смущает? Объект занят самокопированием. Синтаксически здесь всё корректно.
Если такая вот авто-инициализация разрешена, причем, не только для POD типов, тогда вся инкапсуляция, всякое сокрытие данных, идиомы pImpl — все накрывается медным тазом, ибо защитить инкапсулированные данные становится просто невозможно:
class A
{
public:
A() : p(std::make_shared<int>()) {}
int value() const { return *p; }
void set_value(int value) { *p = value; }
private:
std::shared_ptr<int> p;
};
Казалось бы, указатель надежно инкапсулирован. Но стоит только написать "A a(a)" и все обрушилось:
Здравствуйте, Croessmah, Вы писали:
C>Тоже самое происходит и в Вашем коде. У Вас есть только буфер байт, в нем нет объекта типа str, т.е. Ваш код занимается тем же самым — копированием из объекта, время жизни которого еще не началось.
Не то, что не началось, а никогда и не начиналось, потому что это просто кусок памяти. Для POD-типов это нормально, я же специально сделал на этом акцент.
--
Не можешь достичь желаемого — пожелай достигнутого.
R> Нет, не может быть, чтобы это было разрешенным способом инициализации для не POD-типов!
Дело в доступности самого имени в этом контексте, а не том является ли тип POD'ом. У компилятора нет физической способности проверить передаете Вы в конструктор копирования этот же объект или какой-то другой:
A const & at(A const *);
//...
A a(at(&a));//Неизвестно вернет at ссылку на a или на другой объект
Здравствуйте, Croessmah, Вы писали:
C>Вы можете в конструкторе копирования сравнить this с адресом переданного объекта, как это обычно делают в операторе присваивания.
То есть явно всегда писать конструкторы копирования только для того, чтобы проверить на this? Ну это вообще уже жесть какая-то.
C>Дело в доступности самого имени в этом контексте, а не том является ли тип POD'ом. У компилятора нет физической способности проверить передаете Вы в конструктор копирования этот же объект или какой-то другой:
Ты продолжаешь доказывать, что синтаксически все правильно. Так с этим никто и не спорил. UB потому и существует в природе, что комилятор не способен его задетектить. И ответственнось в этом случае на программисте, а не на компиляторе.
--
Не можешь достичь желаемого — пожелай достигнутого.
A trivial default constructor is a constructor that performs no action. All data types compatible with the C language (POD types) are trivially default-constructible. Unlike in C, however, objects with trivial default constructors cannot be created by simply reinterpreting suitably aligned storage, such as memory allocated with std::malloc: placement-new is required to formally introduce a new object and avoid potential undefined behavior.
Здравствуйте, rg45, Вы писали:
R>Ты продолжаешь доказывать, что синтаксически все правильно. Так с этим никто и не спорил. UB потому и существует в природе, что комилятор не способен его задетектить. И ответственнось в этом случае на программисте, а не на компиляторе.
Я не об этом пытаюсь сказать. Я предположил,что Вы сомневаетесь в правильности синтаксиса. Поэтому и спросил, уж не синтаксис ли Вас смущает, раз есть сомнения в корректности кода, ведь Вы же тоже привели код с UB (кстати, в нем лучше использовать std::aligned_storage вместо std::array, т.к можно будет указать правильное выравнивание).
Здравствуйте, Croessmah, Вы писали:
R>>Ты продолжаешь доказывать, что синтаксически все правильно. Так с этим никто и не спорил. UB потому и существует в природе, что комилятор не способен его задетектить. И ответственнось в этом случае на программисте, а не на компиляторе.
C>Я не об этом пытаюсь сказать. Я предположил,что Вы сомневаетесь в правильности синтаксиса. Поэтому и спросил, уж не синтаксис ли Вас смущает, раз есть сомнения в корректности кода, ведь Вы же тоже привели код с UB (кстати, в нем лучше использовать std::aligned_storage вместо std::array, т.к можно будет указать правильное выравнивание).
Нет-нет, значит, я не очень удачно выразился, синтаксис вопросов не вызывал. Интересовала лишь корректность с точки зрения UB.
То есть, UB, все-таки, правильно я понимаю? Для всех типов, или только для non-POD? И как это обосновать с точки зрения стандарта, чтоб уже расставить все точки над "i" — "Object LIfetime", или еще как-то?
--
Не можешь достичь желаемого — пожелай достигнутого.
Если речь о том, чтобы попытаться вызвать конструктор template<bool B> str() извне, то, насколько мне известно, такой вызов не поддерживается. Впрочем, изнутри класса он тоже не поддерживается.
Есть две конструкции, где такой конструктор имел бы какой-то смысл и его можно было бы вызывать: внутри placement new и для вызова конструктора делегирования.
Например:
BFE>Если речь о том, чтобы попытаться вызвать конструктор template<bool B> str() извне, то, насколько мне известно, такой вызов не поддерживается. Впрочем, изнутри класса он тоже не поддерживается.
Дьявол, как обычно, прячется в мелочах. Задача — создать объект данного класса. А каким именно конструктором, об этом никто ничего не говорил.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Дьявол, как обычно, прячется в мелочах. Задача — создать объект данного класса. А каким именно конструктором, об этом никто ничего не говорил.
R>То есть, UB, все-таки, правильно я понимаю?
Комитет решил, что инициализация объекта самим собой с использованием конструктора копий сама по себе к UB не приводит http://wg21.link/cwg363 (но UB может возникнуть, например, из-за чтения indeterminate value из дата мемберов).
Правда, решил он давно и через ~год появился другой issue http://wg21.link/cwg453, который пока не закрыт и который имеет отношение к такой инициализации самим собой.