Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Новая семантика ... , частичные CTAD, неименованные локалы и т.д. #565

Open
kelbon opened this issue Jun 19, 2023 · 2 comments
Labels
Помощь советом Идея прорабатывается другими участниками международного коммитета

Comments

@kelbon
Copy link

kelbon commented Jun 19, 2023

Увидел пропозал в С++26 на auto _ которое бы заменялось на [[maybe_unused]] auto x и сгорело немного

Кажется существуют способы гораздо лучше с точки зрения языка, которые решают сразу несколько проблем, моё предложение решает проблемы:

  • множества make* функций
  • неименованных локалов(которые хочется не именовать)
  • structured binding и рефлексия на его основе
  • более удобное метапрограммирование и новые возможности в нём(понятные и логичные)
  • решение проблемы "как написать универсальное is_specialization_of"
  • и т.д.

Итак, первая часть пропозала:

auto [...args] = x;          // структурная привязка в вариадик
auto [a, b, ...args] = x;  // два первых аргумента обычные, остальные вариадик
auto [a, ...] = x;            // первый аргумент обычный, остальные НЕИМЕНОВАННЫЙ вариадик
auto [..., a] = x;            // выделение последнего и неименованный вариадик в начале
auto [a, ..., b] = x;        // и даже так, если tuple_size_v < 2, то программа ill formed
// это можно также использовать для создания неименованных переменных
// std::get для lock_guard возвращает *this чтобы это было возможно
auto [...] = std::lock_guard(mtx);
// std::scoped_lock это буквально логический тупл локов
auto [...] = std::scoped_lock(mtxs...);

Вторая часть пропозала:

В контексте декларации шаблонных аргументов ... X будет означать пак любых аргуменов, например здесь Args это пак ЛЮБЫХ аргументов, не только типов

template<... Args>

Это позволяет сделать следующее

template<typename>
struct is_specialization : std::false_type {};

template<...Args, template<...> typename Template>
struct is_specialization<Template<Args...>> : std::true_type {};

Контекст декларации аргументов функции

// это шаблон функции с неименованным паком аргументов аналогично тому как работает void foo(auto);
void foo(vector<int, ...>); 
// эквивалентно этому переписанному коду(если бы были аргументы не типы у шаблона, то добавило бы их тоже)
template<typename... Args>
void foo(vector<int, Args...>)

// Аналогично для
void foo(vector<...>);         // неименованный пак
void foo(vector<... Args>); // именованный пак
template<typename Alloc>
void foo(vector<int, Alloc, ...>); // тоже работает, сейчас на гцц такое поведение поддержано

void foo(vector<..., int, ...>); // ошибка компиляции
void foo(vector<...> v, unique_ptr<...>); // работает

Контекст передачи шаблонных шаблонных аргументов
Template<Type, ...> - алиас на Template с requires что первый тип same_as
Пример:

view | to<vector<int, ...>> // переписывается в то что ниже

template<same_as<int> T, ... Args> // all args, not just types
using __alias_vector = vector<T, Args...>;
view | to<vector<int, ...>>

Контекст вывода типов переменных (CTAD)

// применяет частичный CTAD с переданным пользователем типом int
vector<int, ...> x = vector<float, myaloc>();
// выполняет полный CTAD
vector<...> x = vector<int>();

Механизм работы частичного CTAD:
У компилятора имеются дедакт гайды, в некоторых из них типы СПРАВА undeductible, в этом случае это называется частичный дедакт гайд(сейчас это запрещено)
При передаче пользователем части аргументов компилятор подставляет их и некоторые из частичных дедакт гайдов становятся полными, после этого компилятор делает обычный CTAD как сейчас(это похоже на C++20 фичу с дедакт гайдом из алиасов, просто фактически как и выше Template<Args, ...> создаёт алиас по которому компилятор выводит полный тип)

Пример:

// это частичный дедакт гайд
// компилятор видит что тип U в типе справа невыводим, но когда пользователь сам передаёт тип U
// компилятор имеет всю информацию чтобы вывести тип
template<typename T, typename U, typename Alloc>
vector(vector<T, Alloc>) -> vector<U, Alloc>;

// использование. Компилятор видит слева int, подставляет в дедакт гайд,
// остаётся вывести аллокатор, дедакт гайд подсказывает, что он my_alloc
vector<int, ...> v = vector<float, my_alloc>{};

Этот частичный дедакт гайд также можно переписать с помощью пропозала короче

template<typename Alloc>
vector(vector<..., Alloc>) -> vector<..., Alloc>;  // использованы два неименованных пака, разных
@apolukhin
Copy link
Member

Первую часть скоро примут в стандарт в https://wg21.link/P1061

Вторая часть весьма противоречива и требует прототипа. Если напишите - будет круто, а без него - идея обречена на провал

@apolukhin apolukhin added the Помощь советом Идея прорабатывается другими участниками международного коммитета label Mar 24, 2024
@kelbon
Copy link
Author

kelbon commented Mar 24, 2024

Первую часть скоро примут в стандарт в https://wg21.link/P1061

Вторая часть весьма противоречива и требует прототипа. Если напишите - будет круто, а без него - идея обречена на провал

отлично, хорошо что ещё добавили для index_sequence раскрытие, (тут я об этом не писал, но в других местах при обсуждении этой фичи упоминал не раз)
А где посмотреть на статус, как определить, что "скоро примут"?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Помощь советом Идея прорабатывается другими участниками международного коммитета
Projects
None yet
Development

No branches or pull requests

2 participants