Здравствуйте, Videoman, Вы писали:
NB>>код?
V>В строчке 496 именно в VS2013 после копирования optCopy == 1, а не 1234. Я сейчас не очень красиво выгляжу, но я что-то не могу найти online компилятор для VS2013, и не могу вам это наглядно показать. V>На VS2015, VS2017, VS2019 на GCC которые мне доступны ваше исправления отлично работает. В случае копирования optional вызывается оператор копирования, как я и ожидал. Я склоняюсь к тому что это опять глюк компилятора VS2013. На ней при копировании вызывается optional(OtherType&& value, std::decay_t<compatible_t<OtherType>>*) с параметром шаблона optional<int> ???
Здравствуйте, Videoman, Вы писали:
V>Здравствуйте, rg45, Вы писали:
V>Вот, постарался как можно более компактно изобразить проблему.
V>Строчка 489 — не правильно разрешается перегрузка в случае std::optional, пока не могу понять почему. Буду очень признателен если вы посоветуете как наиболее минимальными изменениями можно это пофиксить. V>Не спрашивайте почему используется собственная реализация std::optional, но хотелось бы, по возможности, сейчас использовать именно ее .
Казалось бы, задачу можно решить определив оператор приведения типа у класс Container, но вышеописанные выражения являются вызовами конструкторов инициализации, а следовательно у классов со сложными конструкторами (типа string) сначала срабатывают перегрузки конструкторов, а не операторов приведения типа. Следовательно нужная схема не работает. Как-нибудь просто можно решить задачу в рамках современного С++ ?
Здравствуйте, Videoman, Вы писали:
V>Казалось бы, задачу можно решить определив оператор приведения типа у класс Container, но вышеописанные выражения являются вызовами конструкторов инициализации, а следовательно у классов со сложными конструкторами (типа string) сначала срабатывают перегрузки конструкторов, а не операторов приведения типа. Следовательно нужная схема не работает. Как-нибудь просто можно решить задачу в рамках современного С++ ?
Все должно работать, лишь бы только не возникало коллизии между разными пользовательскими преобразованиями. Единственное что, наверное, операторы преобразования стоит объявлять явными (с ключевым слово "explicit"), ну и инициализацю оформлять через скобки, а не через знак присваивания.
Строчка 489 — не правильно разрешается перегрузка в случае std::optional, пока не могу понять почему. Буду очень признателен если вы посоветуете как наиболее минимальными изменениями можно это пофиксить.
Не спрашивайте почему используется собственная реализация std::optional, но хотелось бы, по возможности, сейчас использовать именно ее .
Самом деле проблема глубже, на мой взгляд. Любой класс внутри контейнера который принимает один шаблонный параметр без explicit, будет пытаться вызывать конструктор инициализации вместо оператора приведения типа контейнера. Если я ошибаюсь поправьте меня.
P.S. Я в курсе что моя реализация optional сильно урезана и во многом не соответствует стандарту, но от нее много и не требуется. По ряду причин, я не могу использовать сторонние библиотеки (boost и т.д.) и пока-что, на данной итерации, мы все еще используем VS2013, где нет optional. Со стандартным optional из поставки VS2017 ваш пример работает. В будущем после переходе на C++17 все заработает, но нужно что-то предпринять сейчас.
Здравствуйте, Videoman, Вы писали:
V>Вот, постарался как можно более компактно изобразить проблему.
V>Строчка 489 — не правильно разрешается перегрузка в случае std::optional, пока не могу понять почему. Буду очень признателен если вы посоветуете как наиболее минимальными изменениями можно это пофиксить.
Ну это понятно почему — в цепочке присутствуют два последовательных пользовательских преобразования — оператор приведения Container и преобразующий конструктор optional, тогда как стандарт позволяет только одно. Тут нужна либо специализированная конвертирующая функция, либо явное преобразование к int:
const std::optional<int> v5(int(cont5));
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Ну это понятно почему — в цепочке присутствуют два последовательных пользовательских преобразования — оператор приведения Container и преобразующий конструктор optional, тогда как стандарт позволяет только одно. Тут нужна либо специализированная конвертирующая функция, либо явное преобразование к int:
R>
R>const std::optional<int> v5(int(cont5));
R>
Ну вот мне пока не очень понятно . Почему в той же ситуации стандартный std::optional работает как и ожидается ? Там как-то хитро объявляется преобразующий конструктор optional(U&&), если я правильно вас понял. И потом:
R>Ой, что-то я сомневаюсь, что это поможет — с учетом того, что compatible_t реализован через is_constructible. Заколдованный круг же.
по крайней мере компилер не ругается
в первом конструкторе вообще смысла немного, т.к. сфинае не работает.
к томуже is_constructible к другому типу идет
Сработало!!! Вот спасибо вам большое! Был бы очень вам признателен если вы объясните ваше заклинание ???
Для себя, я так понимаю что мы накладываем определенные ограничения (концепт для бедных, так сказать) на передаваемый типы, и данный конструктор по SFINAE выпадает из части перегрузок, но хотелось бы понять точно в чем была моя ошибка.
Здравствуйте, Videoman, Вы писали:
V>Сработало!!! Вот спасибо вам большое! Был бы очень вам признателен если вы объясните ваше заклинание ??? V>Для себя, я так понимаю что мы накладываем определенные ограничения (концепт для бедных, так сказать) на передаваемый типы, и данный конструктор по SFINAE выпадает из части перегрузок, но хотелось бы понять точно в чем была моя ошибка.
compatible_t отсекает левые варианты, но чтобы оно сработало, ему нужно подать тип, который пришел из параметров.
находясь первым аргументом он этот тип никак не получит.
std::decay просто очищает тип от ссылки, чтобы можно было иметь указатель и не возиться с параметрами по умолчанию.
Здравствуйте, Videoman, Вы писали:
R>>Ну это понятно почему — в цепочке присутствуют два последовательных пользовательских преобразования — оператор приведения Container и преобразующий конструктор optional, тогда как стандарт позволяет только одно. Тут нужна либо специализированная конвертирующая функция, либо явное преобразование к int:
R>>
R>>const std::optional<int> v5(int(cont5));
R>>
V>Ну вот мне пока не очень понятно . Почему в той же ситуации стандартный std::optional работает как и ожидается ? Там как-то хитро объявляется преобразующий конструктор optional(U&&), если я правильно вас понял.
Только сейчас досмотрелся, насчет двойного пользовательского преобразования это я прогнал — в твоей реализации такого конструктора просто нет
В твоем случае конструктор не подхватывается потому, что его шаблоныый параметр просто не может быть выведен (потому что тип параметра конструктора это просто завуалированный XXX<YYY>::type — в принцие невыводимая конструкция) А значит и сам конструктор в принципе не может быль использован.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Videoman, Вы писали:
V>Я поспешил на счет исправления. Код теперь компилируется, но ломается operator=, т.к. теперь постоянно срабатывает конструктор приведения типа.
Здравствуйте, rg45, Вы писали:
R>В твоем случае конструктор не подхватывается потому, что его шаблонный параметр просто не может быть выведен (потому что тип параметра конструктора это просто завуалированный XXX<YYY>::type — в принцие невыводимая конструкция) А значит и сам конструктор в принципе не может быль использован.
В поиске ответа я исхожу из того, что стандартный optional работает, значит есть кокой-то способ заставить этот синтаксис работать.
Мне кажется в стандартном optional конструктор преобразования optional(Other&& opt) не простой, а условный, он просто пропадает при разрешении перегрузки если мы пытаемся подать в конструктор optional не совместимый тип, и тогда уже срабатывает оператор преобразования типа, как-то так.
Здравствуйте, Videoman, Вы писали:
R>>В твоем случае конструктор не подхватывается потому, что его шаблонный параметр просто не может быть выведен (потому что тип параметра конструктора это просто завуалированный XXX<YYY>::type — в принцие невыводимая конструкция) А значит и сам конструктор в принципе не может быль использован.
V>В поиске ответа я исхожу из того, что стандартный optional работает, значит есть кокой-то способ заставить этот синтаксис работать. V>Мне кажется в стандартном optional конструктор преобразования optional(Other&& opt) не простой, а условный, он просто пропадает при разрешении перегрузки если мы пытаемся подать в конструктор optional не совместимый тип, и тогда уже срабатывает оператор преобразования типа, как-то так.
Ну если ты безусловно добавишь конструктор optional(Other&&) у тебя тоже все заработает. Весь фокус в том, чтобы корректно выбросить этот конструктор из рассмотрения для несовместимых типов. Способ, предложенный night beast должен работать.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, night beast, Вы писали:
NB>Здравствуйте, Videoman, Вы писали:
V>>Я поспешил на счет исправления. Код теперь компилируется, но ломается operator=, т.к. теперь постоянно срабатывает конструктор приведения типа.
NB>код?
В строчке 496 именно в VS2013 после копирования optCopy == 1, а не 1234. Я сейчас не очень красиво выгляжу, но я что-то не могу найти online компилятор для VS2013, и не могу вам это наглядно показать.
На VS2015, VS2017, VS2019 на GCC которые мне доступны ваше исправления отлично работает. В случае копирования optional вызывается оператор копирования, как я и ожидал. Я склоняюсь к тому что это опять глюк компилятора VS2013. На ней при копировании вызывается optional(OtherType&& value, std::decay_t<compatible_t<OtherType>>*) с параметром шаблона optional<int> ???
Здравствуйте, rg45, Вы писали:
R>Ну если ты безусловно добавишь конструктор optional(Other&&) у тебя тоже все заработает. Весь фокус в том, чтобы корректно выбросить этот конструктор из рассмотрения для несовместимых типов. Способ, предложенный night beast должен работать.
Да, это изначально и было моей идеей, но самому оказалось сложно правильно придумать такой "концепт".
NB>при OtherType == std::optional NB>дает не то значение, что хранится в value?
Нет. Вот, как-раз сейчас, сижу с этим разбираюсь. У меня голова сейчас немного обалдела от этого optional. Почему реакция идет с такими задержками: дело в том, что у меня огромная библиотека и, как раз, там есть собственная реализация std::optional для 13-й Студии. Также, все обложено кучей моих же тестов, которые как раз сейчас валятся. Если вы уже поняли в чем ошибка и как лучше исправить — буду вам премного благодарен.
Здравствуйте, night beast, Вы писали:
NB>а, там оператор каста к бул есть.
Есть, и у VS2013 есть баг, который не видит explicit в этой ситуации и кастит к bool . По-этому и была единица.
Здравствуйте, Videoman, Вы писали:
NB>>а, там оператор каста к бул есть. V>Есть, и у VS2013 есть баг, который не видит explicit в этой ситуации и кастит к bool . По-этому и была единица.
для каста к бул есть safe bool idiom, можно ее попробовать