Мне было любопытно, определено ли в C++23 поведение, позволяющее иметь template
-template
, принимающий typename
, и иметь возможность вставлять template
, который принимает concept
(который accepts
a typename
)?
Вот пример:
#include <iostream>
#include <type_traits>
template<typename T>
concept MyConcept = std::is_integral_v<T> || std::is_floating_point_v<T>;
template<template<typename> typename TT>
struct A {
template<typename T>
using Type = TT<T>;
};
template<MyConcept T>
struct B {
T bb;
};
int main(int argc, char** args)
{
auto a = A<B>{}; // Ok? Compiles with gcc 13.2.1 and clang-16.0.6
auto b = decltype(a)::Type<int>{};
return 0;
}
Обратное тоже, кажется, компилируется, что делает меня еще более подозрительным.
template<template<MyConcept> typename TT>
struct A {
template<typename T>
using Type = TT<T>;
};
template<typename T>
struct B {
T bb;
};
int main(int argc, char** args)
{
auto a = A<B>{}; // Ok? Compiles with gcc 13.2.1 and clang-16.0.6
auto b = decltype(a)::Type<int>{};
return 0;
}
Здесь, при определенном прочтении, мы должны принять template
в template
-template
, если этот шаблон принимает MyConcept
, но B
в template
является неограниченным?
Являются ли эти примеры неопределенным поведением или они ведут себя так, как определяет стандарт?
Спасибо!
Обновленный пример выглядит хорошо. И он компилируется всеми компиляторами. И я не вижу причин, по которым это должно быть неопределенное поведение.
@user12002570 user12002570 Я хотел бы создать библиотеку, которая может в конечном итоге полагаться на это поведение, и я просто хочу проверить, что она определена. Причина моих подозрений в том, что многие, казалось бы, безобидные вещи являются UB, например, имена, начинающиеся с подчеркивания, которое есть во многих программах godbolt.org/z/GjhYhx4n3 получится ли что-нибудь из этого? Вероятно, нет, даже cppreference, кажется, противоречит сам себе по поводу погоды или нет, вы можете специализироваться std::char_traits
en.cppreference.com/w/cpp/string/char_traits en.cppreference.com/w/cpp/language/extending_std
Концепции — это новая особенность теории относительности, и это кажется странным крайним случаем, поэтому я и спрашиваю:
Да, я понимаю. C++ полон сюрпризов. Многие простые на вид вещи в C++ представляют собой UB. Так что можно задаться вопросом, так ли это. Моя главная мысль заключается в том, что вы пытались прочитать стандарт, чтобы узнать, UB это или нет. Вопрос сам по себе достаточно хорош, и я только хочу, чтобы люди хотя бы один раз попробовали прочитать стандарт самостоятельно, чтобы разобраться. В противном случае люди могут просто опубликовать любой (бесконечное количество) рабочих фрагментов кода и начать спрашивать, является ли этот фрагмент UB только потому, что он им кажется подозрительным.
Вы правы, я, честно говоря, должен был это сделать, я смотрю на это сейчас (никогда особо не смотрел на это раньше, немного пугает, если честно, в любом случае только что создал документ), это выглядит как пример 4 в разделе 13.4.4, параграф 3 C. Стандарт ++23, возможно, демонстрирует именно этот случай, и пример 3 также выглядит актуальным.
Вот список стандартных PDF-файлов различных версий C++, которые я использую очень часто, чтобы вам не приходилось создавать документ снова и снова. Можно скачать документ в формате PDF напрямую оттуда. Это должно ускорить процесс.
@user12002570 Спасибо! Это должно быть на isocpp.org/std/the-standard
Согласно общедоступному рабочему проекту стандарта C++23, похоже, что это определенное поведение и оно правильное. Пример 4 в параграфе 3 § 13.4.4, похоже, показывает именно это из стандарта:
template<typename T> concept C = requires (T t) { t.f(); };
template<typename T> concept D = C<T> && requires (T t) { t.g(); };
template<template<C> class P> struct S { };
template<C> struct X { };
template<D> struct Y { };
template<typename T> struct Z { };
S<X> s1; // OK, X and P have equivalent constraints
S<Y> s2; // error: P is not at least as specialized as Y
S<Z> s3; // OK, P is at least as specialized as Z
Также это из примера 2 выглядело актуальным:
template<auto n> class D { /* ... */ };
//...
template<template<int> class R> class Z { /* ... */ };
//...
Z<D> zd; // OK
Обновленный пример