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:
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.
A bit hard to define "what's a container". The below checks for value_type
, iterator
, and const_iterator
nested typedefs. Tweak the void_t
check as you want. (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.)
Note that dimension_impl
's specialization calls 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).
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):
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
:
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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.