Здравствуйте. Нужен трейт, чтобы определял, можно ли создать создать объект на куче используя стандартный new или placement new:
auto x = new X();
auto x2 = new (malloc(sizeof(X))) X();
По идее, ограничения два — должен быть публичный конструктор по умолчанию (или с аргументами по умолчанию..., но это не важно), и оператор new не должен быть каким-то образом запрещён.
Поэтому, стандартный std::is_default_constructible не подходит (он, я так понимаю, проверяет возможность создания на стеке и поэтому учитывает доступность деструктора).
Есть какой-то прямой и очевидный способ проверить это, а то велоипеды работают плохо и не везде
Здравствуйте, Went, Вы писали:
W>Здравствуйте. Нужен трейт, чтобы определял, можно ли создать создать объект на куче используя стандартный new или placement new: W>
W>auto x = new X();
W>auto x2 = new (malloc(sizeof(X))) X();
W>
Как я догадываюсь, концепты не предлагать? Тогда старый добрый SFINAE:
Здравствуйте, rg45, Вы писали:
R>Как я догадываюсь, концепты не предлагать? Тогда старый добрый SFINAE...
Супер, работает! Честно сказать, я искал ошибку в чужом коде, и там было сделано приблизительно так (обрати внимание на void):
В результате, для объектов, у которых определен пользовательский оператор new и защищенный деструктор, VS2019 кидало ошибку, так как почему-то пыталось получить доступ к деструктору (точнее, из-за SFINAE молча разрешалось в общую форму шаблона). Я вроде пытался сделать без void, но что-то тоже не работало.
Здравствуйте, Went, Вы писали:
W>Здравствуйте, rg45, Вы писали:
R>>Как я догадываюсь, концепты не предлагать? Тогда старый добрый SFINAE... W>Супер, работает! Честно сказать, я искал ошибку в чужом коде, и там было сделано приблизительно так (обрати внимание на void):
W>
W>В результате, для объектов, у которых определен пользовательский оператор new и защищенный деструктор, VS2019 кидало ошибку, так как почему-то пыталось получить доступ к деструктору (точнее, из-за SFINAE молча разрешалось в общую форму шаблона). Я вроде пытался сделать без void, но что-то тоже не работало.
Так у тебя вторым параметром шаблона заявляется функция void(T*), для нее чтобы вывести T* идет обращение на operator new, если он закрыт или удален — будет ошибка Это я прогнал. Просто детектор не работает как должно в этом случае, не правильно определяет. И, видимо, на основании не правильной детекции, уже в другом коде идет попытка вызова new и там возникает ошибка..
Вот так работает:
Ну это вообще что-то странное — к void можно привести ОБЪЕКТ какого-то типа (или ссылку), а здесь в качестве аргумента пытаются использовать непостредствено тип, а не объект. Конечно, это не может скомпилиться, ни при каком T. Вероятно, вместо void хотели использовать std::void_t, а потом перемудрили.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Went, Вы писали:
W>>я искал ошибку в чужом коде, и там было сделано приблизительно так (обрати внимание на void):
W>>
R>Ну это вообще что-то странное — к void можно привести ОБЪЕКТ какого-то типа (или ссылку), а здесь в качестве аргумента пытаются использовать непостредствено тип, а не объект. Конечно, это не может скомпилиться, ни при каком T. Вероятно, вместо void хотели использовать std::void_t, а потом перемудрили.
Это не приведение к void, это тип функция void(Arg), и если основной шаблон чуть подправить то это все работает
Здравствуйте, vopl, Вы писали:
V>Это не приведение к void, это тип функция void(Arg), и если основной шаблон чуть подправить то это все работает
Это понятно, что можно реализовать и так и эдак, но если судить по объявлению primary template, похоже, пытались сделать имненно приведение. Хотя, даже если бы это приведение удалось, все равно вышел бы облом, поскольку шаблон ожидает тип, в качестве параметра
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Ну это вообще что-то странное — к void можно привести ОБЪЕКТ какого-то типа (или ссылку), а здесь в качестве аргумента пытаются использовать непостредствено тип, а не объект. Конечно, это не может скомпилиться, ни при каком T. Вероятно, вместо void хотели использовать std::void_t, а потом перемудрили.
Ох, это чисто моя описка, было вот так (это вариант для placement_new):
decltype(void(new (std::declval<T*>()) T()))
То есть умозрительный результат вызова placement new приводился явно к void. Я заменял это на такое
допуская именно ошибку трактовки "то ли функция, то ли приведение", но ничего не менялось — студия упорно хотела доступа к деструктору T. При этом ideone на GCC8 пережёвывал это нормально.
W>допуская именно ошибку трактовки "то ли функция, то ли приведение", но ничего не менялось — студия упорно хотела доступа к деструктору T. При этом ideone на GCC8 пережёвывал это нормально.
Я думаю, что причина в том, что в этом случае использование оператора new является не полным выражением, а подвыражением. В стандарте рыться лениво, но, думаю, вот этому ресурсу можно доверять:
Because no temporary object is created, the type need not be complete or have an available destructor, and can be abstract. This rule doesn't apply to sub-expressions: in decltype(f(g())), g() must have a complete type, but f() need not.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Я думаю, что причина в том, что в этом случае использование оператора new является не полным выражением, а подвыражением. В стандарте рыться лениво, но, думаю, вот этому ресурсу можно доверять: R>https://en.cppreference.com/w/cpp/language/decltype R>
R>Because no temporary object is created, the type need not be complete or have an available destructor, and can be abstract. This rule doesn't apply to sub-expressions: in decltype(f(g())), g() must have a complete type, but f() need not.
Да, наверняка, так и есть. Удивительно, как ты это раскопал. Осталось выяснить, почему нужен доступ к деструктору в выражении, в котором ничего не разрушается? И почему в других компиляторах не требуется. Очередная бага студии?
Здравствуйте, Went, Вы писали:
W>Да, наверняка, так и есть. Удивительно, как ты это раскопал. Осталось выяснить, почему нужен доступ к деструктору в выражении, в котором ничего не разрушается? И почему в других компиляторах не требуется. Очередная бага студии?
Да, похоже, что бага. Ведь результатом (под)выражения является указатель — который всегда является полным типом, даже когда указывает на неполный. И с деструктором указателя тоже никаких вопросов возникать не должно.
--
Не можешь достичь желаемого — пожелай достигнутого.