tjw*_*992 4 c++ templates template-meta-programming c++14
前几天我问了一个关于嵌套向量的非常相似的问题,但我遇到了另一个让我难倒的问题。我需要在编译时获取嵌套向量的最内层类型,以便我可以使用它作为模板参数传递。
例如,如果我有这个嵌套向量:
std::vector<std::vector<std::vector<int>>> v;
Run Code Online (Sandbox Code Playgroud)
我需要一种提取方法,int以便我可以调用一个函数,该函数采用嵌套向量并处理如下元素:
foo<int>(v);
Run Code Online (Sandbox Code Playgroud)
除了问题是这个函数应该能够处理包含任何类型的任何深度的嵌套向量。当我打电话时,foo我希望为我自动推导出内部类型。
所以也许调用看起来像这样:
foo<inner_type_t<v>>(v);
Run Code Online (Sandbox Code Playgroud)
哪里inner_type_t是某种形式的递归模板,int当给定时解析为v。
我认为该解决方案将与另一个问题的解决方案类似,但我无法解决...在递归模板方面,我仍然是一个新手。
这是我到目前为止...
template <typename T>
struct inner_type
{
using type = T;
};
template <typename T>
struct inner_type<std::vector<T>>
{
using type = inner_type<T>;
};
int main()
{
std::vector<std::vector<int>> v = {
{ 1, 2}, {3, 4}
};
std::cout << typeid(inner_type<decltype(v)>::type).name();
}
Run Code Online (Sandbox Code Playgroud)
输出:
struct inner_type<class std::vector<int,class std::allocator<int> > >
Run Code Online (Sandbox Code Playgroud)
哇,我真的很接近哈哈,开始工作了!
我只需要稍微更改模板特化即可正确地递归获取类型。
template <typename T>
struct inner_type
{
using type = T;
};
template <typename T>
struct inner_type<std::vector<T>>
{
// Had to change this line
using type = typename inner_type<T>::type;
};
int main()
{
std::vector<std::vector<int>> v = {
{ 1, 2}, {3, 4}
};
std::cout << typeid(inner_type<decltype(v)>::type).name();
}
Run Code Online (Sandbox Code Playgroud)
输出:
int
Run Code Online (Sandbox Code Playgroud)
遵循Bulletmagnet建议使用value_type成员类型的解决方案:
template<class T, typename = void>
struct inner_type {
using type = T;
};
template<class T>
struct inner_type<T, std::void_t<typename T::value_type>>
: inner_type<typename T::value_type> {};
template<class T>
using inner_type_t = typename inner_type<T>::type;
using VV = std::vector<std::vector<int>>;
static_assert(std::is_same_v<inner_type_t<VV>, int>);
Run Code Online (Sandbox Code Playgroud)
关于如何工作的一个很好的解释可以在这个问题std::void_t中找到。如果专业化格式不正确,它在这里用于默默地拒绝。typename T::value_type
@tjwrona1992 的解决方案是好的,但不允许向量具有不同的分配器。_t另外,让我们使用该特征的一个版本来使其对 C++14 友好。
这应该可以解决问题:
template <typename T> struct inner_type { using type = T; };
template<class T, class Alloc>
struct inner_type<std::vector<T, Alloc>> { using type = typename inner_type<T>::type; };
template<class T>
using inner_type_t = typename inner_type<T>::type;
Run Code Online (Sandbox Code Playgroud)
另外,对于类型名称,您应该使用此处type_name()为 C++14实现的函数 或此处为 C++17 实现的函数。