Следующий код работал в VS2017 и перестал работать в последних VS2022, gcc и clang:
#include <array>
#include <string>
#include <optional>
#include <iostream>
#include <memory>
namespace com
{
template<typename interface_t>
class ptr
{
public:
ptr(interface_t* ptr = nullptr) noexcept { m_ptr = ptr; }
operator interface_t*() const noexcept { return m_ptr; }
private:
interface_t* m_ptr;
};
}
class pin
{
public:
pin(int* v) {};
};
int main()
{
std::array<com::ptr<int>, 10> arr_of_ptr;
for (pin p : arr_of_ptr) // error: no viable conversion from 'value_type'
{
}
pin p1(arr_of_ptr[0]); // ок: case 1
pin p2 = arr_of_ptr[0]; // error: case 2
}
У меня догадка такая, что раньше VS генерировал case1, а теперь по стандарту должен case2, т.е. разные виды инициализации. Вопросы:
1. Прав ли я и теперь по стандарту возможен лишь второй вариант?
2. Можно ли как-то в таком range-for заставить вызваться пользовательское преобразование?
У меня догадка такая, что раньше VS генерировал case1, а теперь по стандарту должен case2, т.е. разные виды инициализации. Вопросы: V>1. Прав ли я и теперь по стандарту возможен лишь второй вариант? V>2. Можно ли как-то в таком range-for заставить вызваться пользовательское преобразование?
— точно! Что-то видимо вчера вечером мой калькулятор user-defined conversion сломался. Это всё компилятор старой студии, слишком жадный был и привычки неправильные формирует. Спасибо!
Здравствуйте, reversecode, Вы писали:
R>поэтому вопрос к студии а не к стандарту
Да я в курсе, что допускается одно user-defined преобразование и бесконечное количество стандартных. Просто старый код отваливается, т.к. писался еще под VS2017.
Здравствуйте, reversecode, Вы писали:
R>особенно задалбывает msvc шный имплиситный конструктор на любую структуру который по умолчанию берет первый елемент структуры
Можно небольшой пример, чтоб понимать, о чем речь?
--
Не можешь достичь желаемого — пожелай достигнутого.
struct A
{
int a;
std::string b;
float c;
//итд
// A(int aa):a(aa){} // не обявив явно не работает в gcc clang
};
int main()
{
auto p = std::make_shared<A>(3);
}
и не только на make_shared
там на много другого тоже самое
на std::map итд
R>struct A
R>{
R> int a;
R> std::string b;
R> float c;
R> //итд
R>// A(int aa):a(aa){} // не обявив явно не работает в gcc clang
R>};
R>int main()
R>{
R> auto p = std::make_shared<A>(3);
R>}
R>
R>и не только на make_shared R>там на много другого тоже самое R>на std::map итд
Так в std::make_shared коструктор используется как раз эксплиситный. И этот пример с успехом компилит не только msvc:
Имплиситный конструктор был бы, если бы компилилось что-то типа такого:
void foo(A);
int main()
{
foo(3);
}
Но такое не компилится, к счастью, нигде, в т.ч. и в msvc.
И вот так можно:
A a_explicit{42}; // OK
А вот так нельзя:
A a_implicit = 42; // error: conversion from 'int' to non-scalar type 'A' requested
А вот если раскомментируешь user-defined конструктор в классе А, то станут возможны оба варианта. Хоть ты и называешь этот конструктор явным, на самом деле, это неявный конструктор — user-defined implicit constructor.
--
Не можешь достичь желаемого — пожелай достигнутого.
Ну это понятно, что виртуальный деструктор блокирует агрегатную инициализацию. Так и в MSVC то же самое. Я не поленился только что попробовал на MSVC 2022, причем, с разными тулсетами и стандартами языка.
Есть пример, который в gcc и clang работает правильно, а в msvc — неправильно?
--
Не можешь достичь желаемого — пожелай достигнутого.
в msvс работает без явного конструктора
в gcc clang нужно конструктор обьявлять явно
где правильно или не правильно я хз, скорее всего не правильно было в msvc
пофиксили ли это в 2022 студии я не проверял
в 2019 это задабывало
если пример все же не срабатывает
значит прийдется лезть в коммиты и искать уточнения по примеру
касательно агрегатной инициализации она тоже нигде не работает
во всех трех компилерах
там вроде для std::list ее как то поправили
но для std::map и еще разного другого не будет работать
где то был пост какого то умного чела на эту тему даже
Здравствуйте, reversecode, Вы писали:
R>в С++17 это не работало
А сейчас у тебя какая студия? Там, начиная с 2017-й (если память меня не подводит), есть возможность переключения тулсетов. Понижение версии тулсета, по идее, должно быть эквивалентно пересадке на более старые версии студии. Ну, понятно, есть опция переключения стандарта языка и есть еще одна, не очень заметная на первый взгляд опция — Conformance Mode. Это типа степень соответсвия требованиям стандарта языка и от этой опции зависит многое. Так что, можно поиграться со всем этим набором, при желании.
--
Не можешь достичь желаемого — пожелай достигнутого.
на clang 15 C++20 это не компилится
но уже на clang 16 и выше с C++20 это комилиться
я clang постоянно как только очередной релиз обновляю, но эти нюансы как что компилилось отваливалось уже не проверяю, компилиться и ладно
на msvc это всегда компилилось с момента заявления поддержки C++20
соответсвенно я сделал выводы что msvc глючит
так как clang и помоему на gcc я это тоже проверял, не компилилось
а теперь получается что это ок
и видимо по правилу агрегатной инициализации вполне нормально брать первый елемент структуры как первый аргумент
соотвественно и примеры выше
я тоже помню что я их с С++20 начинал делать
и там тоже не компилилось без user defined ctor которые повторяли аргументами тот же порядок елементов
тоесть я делал двойную работу