Концепция и параметр имени типа в шаблоне шаблона

Мне было любопытно, определено ли в 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 является неограниченным?

Являются ли эти примеры неопределенным поведением или они ведут себя так, как определяет стандарт?

Спасибо!

Обновленный пример

The Floating Brain 21.02.2024 03:45

Обновленный пример выглядит хорошо. И он компилируется всеми компиляторами. И я не вижу причин, по которым это должно быть неопределенное поведение.

user12002570 21.02.2024 03:48

@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

The Floating Brain 21.02.2024 03:55

Концепции — это новая особенность теории относительности, и это кажется странным крайним случаем, поэтому я и спрашиваю:

The Floating Brain 21.02.2024 03:56

Да, я понимаю. C++ полон сюрпризов. Многие простые на вид вещи в C++ представляют собой UB. Так что можно задаться вопросом, так ли это. Моя главная мысль заключается в том, что вы пытались прочитать стандарт, чтобы узнать, UB это или нет. Вопрос сам по себе достаточно хорош, и я только хочу, чтобы люди хотя бы один раз попробовали прочитать стандарт самостоятельно, чтобы разобраться. В противном случае люди могут просто опубликовать любой (бесконечное количество) рабочих фрагментов кода и начать спрашивать, является ли этот фрагмент UB только потому, что он им кажется подозрительным.

user12002570 21.02.2024 03:59

Вы правы, я, честно говоря, должен был это сделать, я смотрю на это сейчас (никогда особо не смотрел на это раньше, немного пугает, если честно, в любом случае только что создал документ), это выглядит как пример 4 в разделе 13.4.4, параграф 3 C. Стандарт ++23, возможно, демонстрирует именно этот случай, и пример 3 также выглядит актуальным.

The Floating Brain 21.02.2024 04:11

Вот список стандартных PDF-файлов различных версий C++, которые я использую очень часто, чтобы вам не приходилось создавать документ снова и снова. Можно скачать документ в формате PDF напрямую оттуда. Это должно ускорить процесс.

user12002570 21.02.2024 04:14

@user12002570 Спасибо! Это должно быть на isocpp.org/std/the-standard

The Floating Brain 21.02.2024 04:16
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
79
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Согласно общедоступному рабочему проекту стандарта 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

Другие вопросы по теме