Предположим, что я получаю два аргумента шаблону T1 и T2. Если я знаю, что T1 сам является шаблоном (например, контейнером), а T2 может быть любым, возможно ли мне определить базовый тип шаблона для T1 и перестроить его с использованием T2 в качестве аргумента?
Например, если я получаю std::vector<int>
и std::string
, я бы хотел автоматически построить std::vector<std::string>
. Однако, если бы мне дали std::set<bool>
и double
, это произвело бы std::set<double>
.
После просмотра type_traits, соответствующих блогов и других вопросов здесь я не вижу общего подхода к решению этой проблемы. Единственный способ, который я вижу в настоящее время для выполнения этой задачи, - создать адаптеры шаблонов для каждого типа, которые могут быть переданы как T1.
Например, если бы у меня было:
template<typename T_inner, typename T_new>
std::list<T_new> AdaptTemplate(std::list<T_inner>, T_new);
template<typename T_inner, typename T_new>
std::set<T_new> AdaptTemplate(std::set<T_inner>, T_new);
template<typename T_inner, typename T_new>
std::vector<T_new> AdaptTemplate(std::vector<T_inner>, T_new);
Я должен иметь возможность использовать decltype и полагаться на перегрузку оператора для решения моей проблемы. Что-то вроде:
template <typename T1, typename T2>
void MyTemplatedFunction() {
using my_type = decltype(AdaptTemplate(T1(),T2()));
}
Я что-то упустил? Есть ли лучший подход?
ПОЧЕМУ Я хочу это сделать?
Я создаю С++-библиотеку, где я хочу упростить то, что пользователям нужно делать для создания модульных шаблонов. Например, если пользователь хочет создать симуляцию на основе агентов, он может настроить шаблон World с типом организма, менеджером по популяции, менеджером среды и менеджером системы.
Каждый из менеджеров также должен знать тип организма, поэтому декларация может выглядеть примерно так:
World< NeuralNetworkAgent, EAPop<NeuralNetworkAgent>,
MazeEnvironment<NeuralNetworkAgent>,
LineageTracker<NeuralNetworkAgent> > world;
Я бы предпочел, чтобы пользователям не приходилось повторять NeuralNetworkAgent
каждый раз. Если я могу изменить аргументы шаблона, можно использовать аргументы по умолчанию, и приведенное выше можно упростить, чтобы:
World< NeuralNetworkAgent, EAPop<>, MazeEnvironment<>, LineageTracker<> > world;
Плюс легче преобразовать из одного типа мира в другой, не беспокоясь о ошибках типа.
Конечно, я могу справиться с большинством ошибок с помощью static_assert и просто иметь дело с более длинными объявлениями, но я хотел бы знать, возможно ли лучшее решение.