Я пытаюсь написать шаблон класса с переменным пакетом параметров шаблона, который разделен на две группы аргументов. Они должны использоваться в шаблонах участников.
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 {};
Не компилируется.
Возможно ли что-то подобное?
@463035818_is_not_an_ai Реализация работает и проверена на отдельном тестовом стенде. Это не суть проблемы. В любом случае, вот как это работает: в обоих случаях рекурсия используется для определения для каждого типа пакета параметров, к какому кортежу пары он должен принадлежать. Кортеж, содержащий этот тип, затем объединяется с соответствующим кортежем и возвращается. (См. внутри if constexpr).
Почему бы не использовать template <typename Tuple1, typename Tuple2> class Foo;
и template <typename...Ts1, typename... Ts2> class Foo<std::tuple<Ts1..., Ts2...>>{};
?
Я не говорю, что с реализацией что-то не так. Это просто сложно понять, потому что не очевидно, для чего это нужно. Только прочитав вопрос туда и обратно несколько раз, я понимаю, что вы делаете. Конкретный пример поможет понять. Более того, «не работает» лучше иллюстрировать с помощью минимально воспроизводимого примера, который другие могут скомпилировать, чтобы увидеть ошибки.
@ 463035818_is_not_an_ai Хорошо, я добавлю запрошенную информацию, как только смогу.
Кажется, вам нужно что-то вроде template <template <typename...> class Template, typename Tuple> Substitute { using type = ???; };
, которое бы брало tuple<A, B, C>
и производило Template<A. B. C>
. Это достаточно легко организовать.
Я не прошу, а предлагаю. Разница тонкая, но важная ;). Трудно понять, что на самом деле нужно с точки зрения человека, не до конца понимающего вопрос.
Вопрос действительно можно улучшить, 463035818_is_not_an_ai, и я понимаю проблему по-разному, поэтому 2 ответа решают разные проблемы... Хотя оба могут вам помочь :-)
Для меня вопрос заключается в том, чтобы сосредоточиться на объяснении того, как вы пытаетесь чего-то достичь, вместо того, чтобы объяснить, какую проблему должен решить этот шаблон. Что это param_sort
на самом деле должно делать?
@Jarod42 Я не знал, что частичная специализация шаблона позволяет использовать несколько пакетов параметров шаблона с переменным числом вариантов в классе/конструкторе. Ретроспективно ваш подход будет проще, но при этом вы достигнете чего-то похожего. Однако мне потребуется использовать кортежи при инициализации моего объекта. Теперь, когда я углубился в эту тему, просто ради науки/упражнения, я хочу реализовать шаблон класса, который принимает аргументы заданного набора типов в произвольном порядке и может инициализировать правильные поля после их сортировки. аргументы, основанные на их типах.
«Однако мне потребуется использовать кортежи при инициализации моего объекта». Не обязательно, «сгладить» элементы тоже будет нормально (поэтому вместо Foo(std::tuple<Ts1...>t1, std::tuple<Ts2...>t2)
используйте Foo(Ts1...t1, Ts2...t2)
конструктор не является шаблоном Ts1
/Ts2
фиксированы из класса), но CTAD будет проблематично тогда. Но для переупорядочения, по-видимому, требуется промежуточная структура упаковки (как кортеж).
С помощью конструктора делегирования вы можете сделать:
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...>;
};
объясните на примере, как
Args&... args
следует разделить на две группы. Вы сразу же переходите к какой-то реализации, которую трудно понять, пока не станет ясно, какова их цель.