Можно ли использовать модифицированную версию пакета параметров шаблона класса в шаблоне членов?

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

template <class... Args>
class Foo {
public:
    Foo(const Args&... args) :gr1{/*...*/}, gr2{/*...*/} {} 
private:
    template_one<Group1...> gr1;
    template_two<Group2...> gr2;
};

Я придумал следующее:

Сортировщик типов, который возвращает пару кортежей, содержащих отсортированные типы.

template <typename... Args>
struct type_sorter;

template <>
struct type_sorter<> {
    constexpr static auto sort() {return std::pair<std::tuple<>, std::tuple<>>{}; }
};

template <typename Arg, typename... Args>
struct type_sorter<Arg, Args...> {
    constexpr static auto sort() {
        auto ret = type_sorter<Args...>::sort();

        if constexpr (std::is_function_v<Arg>)
            return std::make_pair(std::tuple_cat(ret.first, std::tuple<Arg*>{}), ret.second);
        else
            return std::make_pair(ret.first, std::tuple_cat(ret.second, std::tuple<Arg>{}));
    }
};

Сортировщик параметров, который возвращает пару кортежей, содержащих как отсортированные типы, так и параметры.

template <class Arg>
constexpr auto param_sort(Arg&& arg) {
    if constexpr (std::is_function_v<typename std::remove_reference_t<Arg>>)
        return std::make_pair(std::tuple<Arg>(arg), std::tuple<>());
    else
        return std::make_pair(std::tuple<>(), std::tuple<Arg>(arg));
}

template <class Arg, class... Args>
constexpr auto param_sort(Arg&& arg, Args&&... args) {
    auto ret = param_sort(std::forward<Args>(args)...);

    if constexpr (std::is_function_v<typename std::remove_reference_t<Arg>>)
        return std::make_pair(std::tuple_cat(ret.first, std::tuple<Arg>(arg)), ret.second);
    else
        return std::make_pair(ret.first, std::tuple_cat(ret.second, std::tuple<Arg>(arg)));
}

В настоящее время критерием сортировки является std::is_function. Первый можно использовать для сортировки типов без предоставления аргументов, а второй сортирует как параметры шаблона, так и аргументы. Это полезно, если у вас есть доступ только к пакету параметров шаблона. (В области класса.)

Теперь они оба возвращают кортежи:

Я хотел бы иметь возможность извлекать пакеты параметров (Group1, Group2) из ​​кортежей, сгенерированных сортировщиком типов, и использовать их в объявлении template_one и template_two.

Я попробовал:

template_one<decltype(std::get<
  std::make_index_sequence<std::tuple_size_v<
    decltype(type_sorter<Inputs...>::sort().second)
  >>>(type_sorter<Inputs...>::sort().second)...)
> gr1 {};

Не компилируется.

Возможно ли что-то подобное?

объясните на примере, как Args&... args следует разделить на две группы. Вы сразу же переходите к какой-то реализации, которую трудно понять, пока не станет ясно, какова их цель.

463035818_is_not_an_ai 16.07.2024 15:40

@463035818_is_not_an_ai Реализация работает и проверена на отдельном тестовом стенде. Это не суть проблемы. В любом случае, вот как это работает: в обоих случаях рекурсия используется для определения для каждого типа пакета параметров, к какому кортежу пары он должен принадлежать. Кортеж, содержащий этот тип, затем объединяется с соответствующим кортежем и возвращается. (См. внутри if constexpr).

DominikRzecki 16.07.2024 15:53

Почему бы не использовать template <typename Tuple1, typename Tuple2> class Foo; и template <typename...Ts1, typename... Ts2> class Foo<std::tuple<Ts1..., Ts2...>>{};?

Jarod42 16.07.2024 15:56

Я не говорю, что с реализацией что-то не так. Это просто сложно понять, потому что не очевидно, для чего это нужно. Только прочитав вопрос туда и обратно несколько раз, я понимаю, что вы делаете. Конкретный пример поможет понять. Более того, «не работает» лучше иллюстрировать с помощью минимально воспроизводимого примера, который другие могут скомпилировать, чтобы увидеть ошибки.

463035818_is_not_an_ai 16.07.2024 16:00

@ 463035818_is_not_an_ai Хорошо, я добавлю запрошенную информацию, как только смогу.

DominikRzecki 16.07.2024 16:06

Кажется, вам нужно что-то вроде template <template <typename...> class Template, typename Tuple> Substitute { using type = ???; };, которое бы брало tuple<A, B, C> и производило Template<A. B. C>. Это достаточно легко организовать.

Igor Tandetnik 16.07.2024 16:06

Я не прошу, а предлагаю. Разница тонкая, но важная ;). Трудно понять, что на самом деле нужно с точки зрения человека, не до конца понимающего вопрос.

463035818_is_not_an_ai 16.07.2024 16:09

Вопрос действительно можно улучшить, 463035818_is_not_an_ai, и я понимаю проблему по-разному, поэтому 2 ответа решают разные проблемы... Хотя оба могут вам помочь :-)

Jarod42 16.07.2024 16:46

Для меня вопрос заключается в том, чтобы сосредоточиться на объяснении того, как вы пытаетесь чего-то достичь, вместо того, чтобы объяснить, какую проблему должен решить этот шаблон. Что это param_sort на самом деле должно делать?

Marek R 16.07.2024 17:52

@Jarod42 Я не знал, что частичная специализация шаблона позволяет использовать несколько пакетов параметров шаблона с переменным числом вариантов в классе/конструкторе. Ретроспективно ваш подход будет проще, но при этом вы достигнете чего-то похожего. Однако мне потребуется использовать кортежи при инициализации моего объекта. Теперь, когда я углубился в эту тему, просто ради науки/упражнения, я хочу реализовать шаблон класса, который принимает аргументы заданного набора типов в произвольном порядке и может инициализировать правильные поля после их сортировки. аргументы, основанные на их типах.

DominikRzecki 19.07.2024 20:30

«Однако мне потребуется использовать кортежи при инициализации моего объекта». Не обязательно, «сгладить» элементы тоже будет нормально (поэтому вместо Foo(std::tuple<Ts1...>t1, std::tuple<Ts2...>t2)используйте Foo(Ts1...t1, Ts2...t2) конструктор не является шаблоном Ts1/Ts2 фиксированы из класса), но CTAD будет проблематично тогда. Но для переупорядочения, по-видимому, требуется промежуточная структура упаковки (как кортеж).

Jarod42 20.07.2024 16:38
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
11
77
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

С помощью конструктора делегирования вы можете сделать:

template <class... Args>
class Foo {
    using Tuple1 = decltype(type_sorter<Args...>::sort())::first_type;
    using Tuple2 = decltype(type_sorter<Args...>::sort())::second_type;

    Foo(const std::pair<Tuple1, Tuple2>& p) :gr1{p.first}, gr2{p.second} {}

public:
    Foo(const Args&... args) : Foo(param_sort(args...)) {}

private:
    Tuple1 gr1;
    Tuple2 gr2;
};

Демо

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

Если я правильно понимаю вопрос, вы ищете способ получить foo<A...> немного std::tuple<A...>.

Вы можете написать для этого черту:

template <template <typename ...> class T,typename A> 
struct tuple_expander;

template <template <typename ...> class T,typename ...B>
struct tuple_expander<T,std::tuple<B...>> {
    using type = T<B...>;
};

Живая демо

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