Constantine
Вообще, цитата с cppreference
An alias template is a template which, when specialized, is equivalent to the result of substituting the template arguments of the alias template for the template parameters in the type-id
Tom
Constantine
Ну вы утверждаете, что using-декларация для enable_if_t не эквивалентна прямой подстановке enable_if_t
Constantine
Хотя в правилах SFINAE и нет явной оговорки о том, что произойдет при провале using-декларации, но
An alias template is a template which, when specialized, is equivalent to the result of substituting the template arguments of the alias template for the template parameters in the type-id
Constantine
Кажется, из этого прямо следует, что нет разницы, написано _t в using или вне его
Constantine
Constantine
Если писать через is_detected, то такие проблемы возникают категорически редко
Tom
Tom
У кого-нить есть права bug зарепортить?
Evgenii
Constantine
их человеческие ресурсы вряд ли бесконечные
Constantine
у меня все работает в проекте, разве что Intellisense фейлит примеров пять
Constantine
я лучше зарепорчу в комитет, что надо в overloaded function address operator resolution добавить ADL
Constantine
вот как жить без этого?
Constantine
https://godbolt.org/g/mPdTvW
Constantine
тебе изи, а у меня 100 строк копипасты из-за трейтов на каждый неймспейс
Constantine
Constantine
вот это вообще нормально, да?
template <typename T>
constexpr std::enable_if_t<
!sfinae::has_nonmember_equal_to_1_<T>::value
&& !sfinae::has_nonmember_equal_to_1_std<T>::value
&& !sfinae::has_nonmember_equal_to_1_utils<T>::value
&& !sfinae::has_nonmember_equal_to_1_atl<T>::value
&& sfinae::has_member_equal_to<T>::value,
typename traits::member_equal_to<T>::result_type
> invoke_equal_to(T const& x, T const& y)
{
static_assert(!traits::has_possible_bad_member_equal_to<T>(), "Please make an implicit declarion of the member == operator");
return x.operator == (y);
}
Constantine
ну то есть у тебя ни один стандартный метод не вызывает ==
Constantine
или никто никогда не забывал перекрывать == в потомке?
Constantine
ну тогда либо ты пишешь на чистом С, либо у вас запрещено наследование или операторы конвенцией 😆
Constantine
А почему тогда ты уверен, что никто не забыл? :)
Constantine
Тут же очень легко - например, человек (а) наследует класс Y : Х у которого X::operator == ради type alias, человек (б) потом дописывает классу Y поле, до свидания
Constantine
человек напишет правильный тест на ==, если знает, что он нужен; при code review аналогично - нужно читать описание предка уже имеющегося класса; в статический анализ я слабо верю, хотя это весьма идейная проверка (проверить все операторы)
Constantine
вообще operator ==, имхо, одно из самых проблемных мест в С++, поскольку завязано на некоторую логическую концепцию типа неполиморфной ссылки, которая в языке отсутствует
🦥Alex Fails
Tom
Constantine
Tom
Constantine
Это нормально :)
Ну то есть вам не кажется, что нужно все-таки делать ADL в такой конструкции? И не видели ли вы предложения по функциональности типа decltype, позволяющей получать адрес последней вычисляемой функции выражения?
🐙 Antony
Constantine
По поводу второго - а можно пример использования?
Проверка вызываемой функции на этапе компиляции. Я могу проверить, может ли быть вызван operator ==, но совершенно никак не могу выяснить, что же за функция будет вызвана, в частности, будет ли при вызове выполнен какой-либо implicit cast
Constantine
По поводу второго - а можно пример использования?
Моя задача диагностировать следующую ошибку (аналогичная при внешнем операторе) при вызове == в обобщенном коде
struct A { bool operator == (A const& other) const { return true; }};
struct B : A { int x; };
bool f() { B b1 = {1}, b2 = {2}; return b1 == b2; }
Constantine
По поводу второго - а можно пример использования?
При этом, overloaded function address resolution позволяет мне вызвать только как надо, но не выполняет ADL, мне приходится писать полностью отдельный trait для каждого namespace, в котором может быть operator ==
🐙 Antony
Может тогда лучше детектить публичное наследование?
Constantine
Можно было бы проверять final-класс, но опять же, std::vector не помечен как final
🐙 Antony
Давайте я в очередной раз попробую подумать пару дней, и найти решение
Evgenii
Constantine
Давайте я в очередной раз попробую подумать пару дней, и найти решение
Я не тороплюсь, я накопипастил там уже кода вида, хорошо хоть буста нет.
template <typename T>
constexpr std::enable_if_t<
!sfinae::has_nonmember_equal_to_1_<T>::value
&& !sfinae::has_nonmember_equal_to_1_std<T>::value
&& !sfinae::has_nonmember_equal_to_1_utils<T>::value
&& !sfinae::has_nonmember_equal_to_1_atl<T>::value
&& sfinae::has_member_equal_to<T>::value,
typename traits::member_equal_to<T>::result_type
> invoke_equal_to(T const& x, T const& y)
{
static_assert(!traits::has_possible_bad_member_equal_to<T>(), "Please make an implicit declarion of the member == operator");
return x.operator == (y);
}
Constantine
🐙 Antony
Evgenii
Class B overloads A and has additional members, but doesn't overloads operator==
Constantine
к сожалению, operator в том же std будет объявлен внешним
Constantine
вообще если пойти чуть дальше в логику, тут нужно что-то вроде концепции неполиморфной ссылки
Constantine
которая гарантирует, что указанный тип - в точности тот, который назван
🐙 Antony
кажется что в ближайшее время только метаклассы это починят
Constantine
(я про модули компиляции, разумеется)
Matwey
🐙 Antony
Мне они не кажутся сырыми, мне они кажутся сложно применимыми в текущем виде
И тем не менее, в текущем виде они самые эффективные.
🐙 Antony
Если примут в текущем виде, скорее всего Boost и Стандартная библиотеки на них перейдут, пара крупных компаний для своих внутренних наработок... А остальные будут подтягиваться в течение лет 15
Constantine
У меня достаточно много кода под генератором, я не знаю ограничений, но по сути у меня ~300 TU которые исключительно потребляют шаблонный код и за счет генератора могут быть перегнаны с опреденной легкостью
Evgenii
Constantine
ну тут детали нужны, в чем возникают проблемы при портировании и почему нельзя раз в минуту перегонять один TU
🐙 Antony
Основная проблема - макросы. Модули их не экспоритруют. А значит не работают include guards и проблемы с
import std.iostream
include <iostream>
🐙 Antony
Не очень легко переходить, потребует больших телодвижений
Evgenii
Constantine
Evgenii
собственно в этом и был спор между шлангом и майками, не?
Evgenii
include guards автоматически можно прагмой заменить
Constantine
а я не знаю, почему в стандарт не приняли
#pragma once
🐙 Antony
pragma once не спасёт, она по идее тоже не экспортируется модулями
Constantine
а это не может быть просто реализовано без проблем?
Constantine
а, не может
Evgenii