Рассмотрим эту концепцию, которая имеет параметр шаблона по умолчанию.
template<class T, class = decltype([]{})>
concept IsDefined = sizeof(T) > 0;
Поскольку каждая лямбда имеет отдельный тип, можно было бы ожидать, что каждый экземпляр IsDefined<X>
будет отличаться.
struct SomeType;
static_assert( false == IsDefined<SomeType> );
struct SomeType
{
// Defined.
};
static_assert( true == IsDefined<SomeType> );
Clang и MSVC согласовывают и компилируют этот код. GCC не выполняет второе статическое утверждение, но только если оценивается первое статическое утверждение.
error: static assertion failed
17 | static_assert( true == IsDefined<SomeType> );
Кто-нибудь из этих компиляторов ошибается? Или это поведение не указано?
Кажется, этот дубликат спрашивает о параметрах функции. И этот вопрос специфичен для понятий.
Не было необходимости вновь поднимать этот вопрос. Обсуждение там вполне применимо и здесь.
@user12002570 user12002570, чтобы внести ясность: я спрашиваю, почему концепции ведут себя иначе, чем поведение и ответы, приведенные в вашей ссылке. Я считаю, что это справедливый вопрос. Кто-нибудь из этих компиляторов ошибается?
class = decltype([]{})
не является функциональным аргументом по умолчанию. Почему вы ожидаете, что он будет отличаться при реализации концепции? Это может быть не указано в стандарте.
@3CxEZiVlQ Я согласен. Интересно, что три основных составителя согласны с тем, что такой параметр шаблона уникален в других контекстах. Возможно, ответом будет «не указано».
Я просто наблюдаю нарушения ODR.
В этом случае нормальной формой IsDefined
является атомарное ограничение sizeof(T) > 0
с тождественным отображением T -> T
; обратите внимание, что второй параметр не отображается в сопоставлении (см. [temp.constr.atomic]/1 ). Ваш код — IFNDR от [temp.constr.atomic]/3:
Если в разных точках программы результат удовлетворения различен для одинаковых атомарных ограничений и аргументов шаблона, программа некорректна и диагностика не требуется.
Значит, «template<typename T> struct dependent_zero : std::integral_constant<std::size_t, 0zu> {}; template<class T, class Unique = decltype([]{})> concept IsDefined = sizeof(T) >= dependent_zero<Unique>::value;
» не будет IFNDR, потому что атомарные ограничения не идентичны?