获取嵌套类 STL 容器中的元素总数
Get total number of elements in a nested STL-like container
我想编写一个 C++ 函数来计算通用嵌套类 STL 容器中 "atomic" 元素的总数,条件如下:
每一层都可以是任何类型的容器。
层数不是先验的
我编写了以下递归函数(使用 here 中的代码):
template <typename T>
size_t get_total_size(const T & var)
{
if ( is_container<typeof(var)>::value ) { // From
typename T::const_iterator iter;
size_t sumsize = 0;
for ( iter = var.begin() ; iter!= var.end() ; iter++ ) {
sumsize += get_total_size(*iter);
}
return sumsize;
} else {
return 1;
}
};
Compiling/linking 这可能有效。
问题是在使用它时(否则,编写它没有任何意义!)不编译,因为实例化在 "atomic" 级别达到没有迭代器的类型,例如,在此代码
typedef vector<int> vint;
typedef vector<vint> vvint;
vvint vec_heap;
for (int i=0; i < 12; i++) {
vec_heap.push_back(vint(2, i));
}
cout << get_total_size(vec_heap) << endl; // Instantiation leads to compilation errors
这可能吗?
编辑:
根据一条评论,它可以用 c++17 来完成......
我为objective写的递归函数是不是有点矫枉过正了?
对于 C++17,您可以使用 if constexpr
:
template <typename T>
size_t get_total_size(const T& var)
{
if constexpr (is_container<T>::value) {
return std::accumulate(var.begin(),
var.end(),
0u,
[](int acc, const auto& e){ return acc + get_total_size(e); });
} else {
return 1u;
}
};
在此之前,您可能会使用重载和 SFINAE:
// this will be called when T is not a container (it is the "atomic" type)
template <typename T, std::enable_if_t<!is_container<T>::value, int> = 0>
size_t get_total_size(const T& var)
{
return 1u;
};
// this will be called for all container types, except for maps
template <typename T, std::enable_if_t<is_container<T>::value, int> = 0>
size_t get_total_size(const T& var)
{
return std::accumulate(var.begin(),
var.end(),
0u,
[](int acc, const auto& e){ return acc + get_total_size(e); });
};
// this will be called for maps
template <typename Key, typename T>
size_t get_total_size(const std::map<Key, T> & var)
{
return std::accumulate(var.begin(),
var.end(),
0u,
[](int acc, const auto& e){ return acc + get_total_size_sfinae(e.second); });
}
如果你不能使用 C++17,或者只是想开放你的函数可以使用什么标准,那么你可以切换到使用两个重载并使用 SFINAE 来确定何时调用每次过载。使用
// this will be called when T is not a container (it is the "atomic" type)
template <typename T, typename std::enable_if<!is_container<T>::value, bool>::type = true>
size_t get_total_size(const T & var)
{
return 1;
}
// forward declare of pair function for associative containers
template <typename T, typename U>
size_t get_total_size(const std::pair<T, U> & var);
// this will be called for all container types
template <typename T, typename std::enable_if<is_container<T>::value, bool>::type = true>
size_t get_total_size(const T & var)
{
size_t sumsize = 0;
for ( auto iter = var.begin() ; iter != var.end() ; ++iter ) {
sumsize += get_total_size(*iter);
}
return sumsize;
}
// this will be called for pair to handle associative containers
template <typename T, typename U>
size_t get_total_size(const std::pair<T, U> & var)
{
return get_total_size(var.first) + get_total_size(var.second);
}
这将从 C++11 开始工作,您可以在此 live example
中看到
我想编写一个 C++ 函数来计算通用嵌套类 STL 容器中 "atomic" 元素的总数,条件如下:
每一层都可以是任何类型的容器。
层数不是先验的
我编写了以下递归函数(使用 here 中的代码):
template <typename T>
size_t get_total_size(const T & var)
{
if ( is_container<typeof(var)>::value ) { // From
typename T::const_iterator iter;
size_t sumsize = 0;
for ( iter = var.begin() ; iter!= var.end() ; iter++ ) {
sumsize += get_total_size(*iter);
}
return sumsize;
} else {
return 1;
}
};
Compiling/linking 这可能有效。 问题是在使用它时(否则,编写它没有任何意义!)不编译,因为实例化在 "atomic" 级别达到没有迭代器的类型,例如,在此代码
typedef vector<int> vint;
typedef vector<vint> vvint;
vvint vec_heap;
for (int i=0; i < 12; i++) {
vec_heap.push_back(vint(2, i));
}
cout << get_total_size(vec_heap) << endl; // Instantiation leads to compilation errors
这可能吗?
编辑: 根据一条评论,它可以用 c++17 来完成...... 我为objective写的递归函数是不是有点矫枉过正了?
对于 C++17,您可以使用 if constexpr
:
template <typename T>
size_t get_total_size(const T& var)
{
if constexpr (is_container<T>::value) {
return std::accumulate(var.begin(),
var.end(),
0u,
[](int acc, const auto& e){ return acc + get_total_size(e); });
} else {
return 1u;
}
};
在此之前,您可能会使用重载和 SFINAE:
// this will be called when T is not a container (it is the "atomic" type)
template <typename T, std::enable_if_t<!is_container<T>::value, int> = 0>
size_t get_total_size(const T& var)
{
return 1u;
};
// this will be called for all container types, except for maps
template <typename T, std::enable_if_t<is_container<T>::value, int> = 0>
size_t get_total_size(const T& var)
{
return std::accumulate(var.begin(),
var.end(),
0u,
[](int acc, const auto& e){ return acc + get_total_size(e); });
};
// this will be called for maps
template <typename Key, typename T>
size_t get_total_size(const std::map<Key, T> & var)
{
return std::accumulate(var.begin(),
var.end(),
0u,
[](int acc, const auto& e){ return acc + get_total_size_sfinae(e.second); });
}
如果你不能使用 C++17,或者只是想开放你的函数可以使用什么标准,那么你可以切换到使用两个重载并使用 SFINAE 来确定何时调用每次过载。使用
// this will be called when T is not a container (it is the "atomic" type)
template <typename T, typename std::enable_if<!is_container<T>::value, bool>::type = true>
size_t get_total_size(const T & var)
{
return 1;
}
// forward declare of pair function for associative containers
template <typename T, typename U>
size_t get_total_size(const std::pair<T, U> & var);
// this will be called for all container types
template <typename T, typename std::enable_if<is_container<T>::value, bool>::type = true>
size_t get_total_size(const T & var)
{
size_t sumsize = 0;
for ( auto iter = var.begin() ; iter != var.end() ; ++iter ) {
sumsize += get_total_size(*iter);
}
return sumsize;
}
// this will be called for pair to handle associative containers
template <typename T, typename U>
size_t get_total_size(const std::pair<T, U> & var)
{
return get_total_size(var.first) + get_total_size(var.second);
}
这将从 C++11 开始工作,您可以在此 live example
中看到