【发布时间】:2016-04-09 02:16:49
【问题描述】:
假设我收到一个模板的两个参数,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()));
}
我错过了什么吗?有更好的方法吗?
我为什么要这样做?
我正在构建一个 C++ 库,我想在其中简化用户构建模块化模板所需的操作。例如,如果用户想要构建基于代理的模拟,他们可能会配置具有生物类型、种群管理器、环境管理器和系统管理器的 World 模板。
每个管理者还需要知道有机体类型,因此声明可能类似于:
World< NeuralNetworkAgent, EAPop<NeuralNetworkAgent>,
MazeEnvironment<NeuralNetworkAgent>,
LineageTracker<NeuralNetworkAgent> > world;
我更希望用户不必每次都重复NeuralNetworkAgent。如果我能够更改模板参数,则可以使用默认参数,以上可以简化为:
World< NeuralNetworkAgent, EAPop<>, MazeEnvironment<>, LineageTracker<> > world;
此外,从一种世界类型转换为另一种世界类型更容易,而无需担心类型错误。
当然,我可以使用 static_assert 处理大多数错误,只处理较长的声明,但我想知道是否有更好的解决方案。
【问题讨论】:
-
我得到的三个答案都很好。 @Barry 的一篇是最彻底的,T.C. 的一篇是最彻底的。最好地解决了我的潜在问题,但我认为 Sam Varshavchik(我接受了)的回答对于解决我提出的问题是最优雅的。非常感谢大家!
-
至于这篇文章是重复的,我确实认为@Ben Voight 指出的那个非常相似,但特别关注 STL。如果所有有问题的模板都来自同一个库,那么肯定还有其他可能的技巧。也就是说,另一个问题也有一些有趣且有用的答案。也就是说,我发现这里提供的答案更针对这个问题并且更直接有用。
-
虽然另一个问题不那么广泛,但答案完全涵盖了您的情况。这就是为什么我的标志会导致横幅显示“您的问题已经在这里有了答案”。
标签: c++ templates c++11 template-meta-programming