[英]Getting the number of dimensions of a std::vector/std::array
Let's say I want a class/struct
type, inheriting from integral_constant<size_t, N>
where N is the dimension and the dimension is achieved as follows: 假设我想要一个
class/struct
类型,它继承自integral_constant<size_t, N>
,其中N是维,并且维实现如下:
template<class T>
struct dimension;
template<class T>
struct dimension<vector<T>> : integral_constant<size_t, 1> {};
template<class T>
struct dimension<vector<vector<T>>> : integral_constant<size_t, 2> {};
And then 接着
cout << dimension<vector<int>>::value; // 1
cout << dimension<vector<vector<int>>>::value; // 2
But obviously this is not perfect, as the number of dimensions can be a infinite (in theory). 但是显然这不是完美的,因为维数可以是无限的(理论上)。 Is there a way to achieve a generic solution to this?
有没有办法实现通用解决方案?
Suggestion: I went in this direction, but no further: 建议:我朝这个方向走,但没有进一步:
template<class T, class... Tn>
struct dimension<vector<Tn...>> : integral_constant<size_t, sizeof...(Tn)> {};
Since std::vector
has other template parameters this wouldn't work. 由于
std::vector
具有其他模板参数,因此无法使用。
A bit hard to define "what's a container". 定义“什么是容器”有点困难。 The below checks for
value_type
, iterator
, and const_iterator
nested typedefs. 下面检查
value_type
, iterator
和const_iterator
嵌套的typedef。 Tweak the void_t
check as you want. 根据需要调整
void_t
检查。 (For instance, if you want only things that can be subscripted to be recognized as containers, then add decltype(std::declval<T&>()[0])
to the list.) (例如,如果只希望将可以下标的内容识别为容器,则将
decltype(std::declval<T&>()[0])
到列表中。)
Note that dimension_impl
's specialization calls dimension
. 请注意,
dimension_impl
的专业化称为dimension
。 this allows you to specialize dimension
for container-like things you don't want to be treated as a container ( std::string
comes to mind). 这使您可以将
dimension
专门用于您不希望被视为容器的类似容器的事物(想到std::string
)。
template<class T> struct dimension;
namespace details {
template<class T, class = void>
struct dimension_impl {
static constexpr std::size_t value = 0;
};
template<class T>
struct dimension_impl<T, std::void_t<typename T::value_type,
typename T::iterator,
typename T::const_iterator>> {
static constexpr std::size_t value = 1 + dimension<typename T::value_type>::value;
};
}
template<class T>
struct dimension : std::integral_constant<std::size_t,
details::dimension_impl<T>::value> {};
You can do this for a std::vector
(note that the template parameter list of a std::vector
is longer than 1): 您可以为做到这一点
std::vector
(注意的模板参数列表std::vector
比1以上):
template<typename T>
struct dimension { static constexpr std::size_t value = 0; };
template<typename T, typename... V>
struct dimension<std::vector<T, V...>>{
static constexpr std::size_t value = 1 + dimension<T>::value;
};
This works instead for a std::array
: 这适用于
std::array
:
template<typename>
struct dimension { static constexpr std::size_t value = 0; };
template<typename T, std::size_t N>
struct dimension<std::array<T, N>>{
static constexpr std::size_t value = 1 + dimension<T>::value;
};
It follows a minimal, working example: 它遵循一个最小的有效示例:
#include<vector>
#include<iostream>
template<typename T>
struct dimension { static constexpr std::size_t value = 0; };
template<typename T, typename... V>
struct dimension<std::vector<T, V...>>{
static constexpr std::size_t value = 1 + dimension<T>::value;
};
int main() {
std::cout << dimension<std::vector<std::vector<int>>>::value << std::endl;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.