C++26 Reflection: определение агрегатного шаблонаC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 C++26 Reflection: определение агрегатного шаблона

Сообщение Anonymous »

Я знаю, что вы можете использовать C++26 Reflection для определения нешаблонных агрегатных типов или даже конкретных специализаций шаблонов (демо).
Мой вопрос: возможно ли также определить весь основной шаблон посредством отражения? Или, может быть, есть способ автоматически определять каждую конкретизированную специализацию шаблона?
Справочная информация:
Я очень воодушевлен предстоящим отражением в C++26, поэтому я немного поигрался с ним в Godbolt, используя сборку отражения clang.
В качестве упражнения я попытался создать именованный кортеж. В частности, я хотел, чтобы имена предоставлялись пользователем, а типы определялись, например:

Код: Выделить всё

Named::Tuple{ .a = 42, .b = "Hello" }; // -> deduces 
(Святой Грааль, конечно, заключался бы в том, чтобы имена также выводились из специального инициализатора, но я совершенно не представляю, как мне подойти к этому с текущим отражением: NamedTuple{ .a=42 }; // синтезирует struct NamedTuple{ int a; )
Я попробовал это специально, потому что мне было интересно, возможна ли именованная библиотека форматирования с отражение. То есть

Код: Выделить всё

format({ .name = "World" });
Мои две лучшие попытки были следующими (Demo - TStr — это просто строковый тип, совместимый с NTTP):
Попытка 1:

Код: Выделить всё

template
struct Named {
template
struct Tuple;

template
static consteval bool instantiate() {
define_aggregate(^^Tuple, {
data_member_spec(^^Ts, { .name = Names.data })...
});
return true;
}

template
requires (instantiate())
Tuple(Ts&&...) -> Tuple;
};
Это выглядело многообещающе, поскольку clang пытался использовать руководство по выводу с [with Ts = ], но затем выдал ошибку, выдав, на мой взгляд, наиболее подходящую диагностику:

Код: Выделить всё

:18:9: note: cannot produce an injected declaration from a non-plainly constant-evaluated context
18 |         define_aggregate(^^Tuple, {
Я не уверен, что такое контекст с неявным константным вычислением, но я думаю, что это просто не разрешено стандартом.
Попытка 2:

Код: Выделить всё

template
struct Named {
template
struct Inner {
struct Tuple;

consteval {
define_aggregate(^^Tuple, {
data_member_spec(^^Ts, { .name = Names.data })...
});
}
};

template
using Tuple = Inner::Tuple;

template
Tuple(Ts&&...) -> Tuple;
};
Технически это не удалось из-за отражения, а потому, что определяемые пользователем направляющие вывода не разрешены для шаблонов псевдонимов. Хотя должен сказать, меня немного смутила диагностика clang:

Код: Выделить всё

:54:5: error: alias template 'Named::Tuple' requires template arguments; argument deduction only allowed for class templates or alias templates
54 |     Named::Tuple{ .a = 42, .b = "Hello" };
Что значит «разрешено только для шаблонов псевдонимов», это шаблон псевдонимов!

Я также пробовал использовать производные от Inner::Tuple вместо псевдонима, чтобы иметь возможность предоставить руководство, но тогда назначенный синтаксис инициализации больше не работает.

Подробнее здесь: https://stackoverflow.com/questions/798 ... e-template
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»