C++11 中的通用 STL 兼容直方图
这是我第一次尝试 C++ 中的通用直方图模板函数,并使用 GCC 4.6 进行测试。但是,我想将 dense_histogram()
和 sparse_histogram()
合并到一个通用的通用函数模板中。问题是特定于密集的构造函数H h(n, 0)
在稀疏版本H中既没有定义也没有相关性h
.有没有办法以某种巧妙的 C++ 常规方式或静态地通过 Boost Type.Traits (#include
) 使用条件编译来解决此问题?
#include <algorithm>
#include <limits>
#include <algorithm>
#include <vector>
#include <unordered_map>
namespace std
{
/*!
* \em Dense Histogram of \p a.
*
* \tparam V is Value Type.
* \tparam C is Count (Bin) Type.
* \tparam H is Histogram Storage Type, typically a vector.
*
* \param[in] x is a set of the input data set
*/
template <class V, class C = size_t, class H = vector<C> >
inline
H dense_histogram(const V & x)
{
typedef typename V::value_type E; // element type
size_t n = (static_cast<C>(1)) << (8*sizeof(E)); // maximum number of possible elements for dense variant
H h(n, 0); // histogram
C bmax = 0; // bin max
for_each(begin(x), end(x), // C++11
[&h, &bmax] (const E & e) { // value element
h[e]++;
bmax = std::max(bmax, h[e]);
});
return h;
}
template <class V, class H = vector<size_t> > H make_dense_histogram(const V & x) { return dense_histogram<V, size_t, H>(x); }
/*!
* \em Sparse Histogram of \p a.
*
* \tparam V is Value Type.
* \tparam C is Count (Bin) Type.
* \tparam H is Histogram Structure Type, typically a unordered_map.
*
* \param[in] x is a set of the input data set
*/
template <class V, class C = size_t, class H = unordered_map<typename V::value_type, C> >
inline
H sparse_histogram(const V & x)
{
typedef typename V::value_type E; // element type
H h; // histogram
C bmax = 0; // bin max
for_each(begin(x), end(x), // C++11
[&h,&bmax] (const E & e) { // value element
h[e]++;
bmax = std::max(bmax, h[e]);
});
return h;
}
template <class V, class H = unordered_map<typename V::value_type, size_t> > H make_sparse_histogram(const V & x) { return sparse_histogram<V, size_t, H>(x); }
}
运行使用
Here is my first try at a generic histogram template function in C++ tested with GCC 4.6. However, I would like to merge dense_histogram()
and sparse_histogram()
into one common generic function template. The problem is that the dense-specific constructor H h(n, 0)
is neither defined nor relevant in the sparse version H h
. Is there a way to solve this in some clever C++ regular way or statically typically using conditional compilation through Boost Type.Traits (#include <boost/type_traits.hpp>
)?
#include <algorithm>
#include <limits>
#include <algorithm>
#include <vector>
#include <unordered_map>
namespace std
{
/*!
* \em Dense Histogram of \p a.
*
* \tparam V is Value Type.
* \tparam C is Count (Bin) Type.
* \tparam H is Histogram Storage Type, typically a vector.
*
* \param[in] x is a set of the input data set
*/
template <class V, class C = size_t, class H = vector<C> >
inline
H dense_histogram(const V & x)
{
typedef typename V::value_type E; // element type
size_t n = (static_cast<C>(1)) << (8*sizeof(E)); // maximum number of possible elements for dense variant
H h(n, 0); // histogram
C bmax = 0; // bin max
for_each(begin(x), end(x), // C++11
[&h, &bmax] (const E & e) { // value element
h[e]++;
bmax = std::max(bmax, h[e]);
});
return h;
}
template <class V, class H = vector<size_t> > H make_dense_histogram(const V & x) { return dense_histogram<V, size_t, H>(x); }
/*!
* \em Sparse Histogram of \p a.
*
* \tparam V is Value Type.
* \tparam C is Count (Bin) Type.
* \tparam H is Histogram Structure Type, typically a unordered_map.
*
* \param[in] x is a set of the input data set
*/
template <class V, class C = size_t, class H = unordered_map<typename V::value_type, C> >
inline
H sparse_histogram(const V & x)
{
typedef typename V::value_type E; // element type
H h; // histogram
C bmax = 0; // bin max
for_each(begin(x), end(x), // C++11
[&h,&bmax] (const E & e) { // value element
h[e]++;
bmax = std::max(bmax, h[e]);
});
return h;
}
template <class V, class H = unordered_map<typename V::value_type, size_t> > H make_sparse_histogram(const V & x) { return sparse_histogram<V, size_t, H>(x); }
}
run using
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您应该简单地将公共部分放在第三个函数中,留下
dense_histogram
和sparse_histogram
来创建h
并调用该实现函数:但是,因为你要求它:当你在容器上工作时,我会假设它们有一个便宜的移动,所以你可以定义一个创建特征来生成你的容器并将其移动到你的本地变量中。然后,您可以编写自己的适当构造函数检测,如下所示:
作为一个方面,不要:将您自己的方法添加到
std
是标准的 UB ([namespace.std] $17.6.4.2. 1 p1):
I think you should simply put only the common parts in a third function leaving
dense_histogram
andsparse_histogram
to createh
and call that implementation function:However since you asked for it: As you are working on containers I would assume they have a cheap move, so you could define a creation trait to generate your container and move that into your local variable. Then you can write your own detection of an appropriate constructor like this:
As a side not: Adding your own methods to
std
is UB by the standard ([namespace.std] $17.6.4.2.1 p1
):