首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于静态模板类的建议

关于静态模板类的建议
EN

Stack Overflow用户
提问于 2011-07-19 08:34:19
回答 3查看 405关注 0票数 4

我有这个问题(直方图)。我有一个真正的空间:[a,b]以某种方式分区([a0=a, a1, a2, ..., b])。分区可以是等空间(a1 - a0 = a2 - a1 = ...)或变量。

我需要一个处理这个问题的类,用一些方法来表示它属于分区bin的值;还有一些方法来查找特定bin的中心等等。

在程序期间,我不喜欢实例化类,只调用以下简单函数

代码语言:javascript
复制
Binner binner(binning);
binner.get_bin(1.3);
binner.get_centerbin(2);

因此,我尝试使用模板编写一个静态类来执行这样的操作:

代码语言:javascript
复制
Binner<binning>::get_bin(1.3);
Binner<binning>::get_centerbin(2);

是个好主意吗?还有别的办法吗?现在我有了一些免费的函数

代码语言:javascript
复制
double get_bin(double bin, Binning binning); // a lot of if/else inside

但我觉得这太容易出错了。

在这里,我的实施:

代码语言:javascript
复制
enum Binning {CELL, LARGE, BE};
const double binning_LARGE[] = {0, 1.2, 1.425, 1.550, 1.800, 2.5};
const double binning_BE[] =  {0, 1.425, 1.550, 2.5};

template<Binning binning>
class Binner
{
public:
    static const double* bins;
    static const int n;
    static int get_bin(double value);
};

template<> const double* myclass<LARGE>::bins = binning_LARGE;
template<> const double* myclass<BE>::bins = binning_BE;

template<> const int myclass<LARGE>::n = sizeof(binning_LARGE) / sizeof(double);
template<> const int myclass<BE>::n = sizeof(binning_BE) / sizeof(double);

template<Binning binning> int myclass<binning>::get_bin(double value)
{
    return find_if(bins, bins + n,
           bind2nd(greater<double>(), value)) - bins - 1;
}

template<> int myclass<CELL>::get_bin(double value)
{
    return static_cast<int>(value / 0.025);
}
  1. 这是一个很好的实现/设计吗?
  2. 是否有办法避免使用n字段使用std::vector?多么?
  3. 有办法把0.025参数化吗?我知道double不能是模板参数,但我是否可以编写类似的内容: Binner<0.025> binner;
  4. 其他/建议?

编辑:

关于第三点为什么我不能这样做:

代码语言:javascript
复制
template<Binning binning, int N=100>
class Binner
{
public:
    static const double* bins;
    static const int n;
    static int bin(double value);
};

...

template<Binning binning, int N> int Binner<CELL, N>::bin(double value)
{
    return static_cast<int>(value / (2.5 / N));
}
EN

回答 3

Stack Overflow用户

发布于 2011-07-19 08:45:56

如果不想实例化类,则您的设计是可以的。实际上,在我看来,这是一种模板元编程。这是否有意义取决于您计划如何重用此模板。

使用std::向量将允许您摆脱变量以保持数组大小,这是肯定的。如果这对你的设计有好处,我不知道.它会将一些复杂性从模板定义转移到二进制定义(现在您可以非常简单地初始化它).

最后,可以实例化模板,向其传递一个常量:

代码语言:javascript
复制
template < Binning binning, unsigned long N, unsigned long M>
class ... {
     <using N>
}
票数 4
EN

Stack Overflow用户

发布于 2011-07-19 10:16:29

你考虑过特质类吗?通常,如果您有要与类中的行为分离的静态信息,则可以考虑创建一个封装它的特性类。

因此,我从默认行为开始:

代码语言:javascript
复制
enum Binning {CELL, LARGE, BE};

template <Binning binning>
struct BinTraits
{
    // default behaviour
    int get_bin(double value) { return value / 0.025; } 
};

然后我会提供特制:

代码语言:javascript
复制
const double binning_LARGE[] = {0, 1.2, 1.425, 1.550, 1.800, 2.5};
const double binning_BE[] =  {0, 1.425, 1.550, 2.5};

template <typename RandomAccessCollectionT>
int get_bin_impl(double value, RandomAccessCollectionT collection, unsigned size)
{
    return find_if(collection, collection + size,
           bind2nd(greater<double>(), value)) - collection - 1;
}

template <>
struct BinTraits<LARGE>
{
    int get_bin(double value) { return get_bin_impl(value, binning_LARGE, sizeof(binning_LARGE) / sizeof(binning_LARGE[0])); } 
};

template <>
struct BinTraits<BE>
{
    int get_bin(double value) { return get_bin_impl(value, binning_BE, sizeof(binning_BE) / sizeof(binning_BE[0])); } 
};

然后,我将实际的容器行为放在另一个需要绑定行为的类中(让我们称之为HashTable):

代码语言:javascript
复制
template <typename BinTraits>
class HashTable
{
public:
    void insert(double value)
    {
        int bin = BinTraits::get_bin(value);
        _bins[bin].insert(value);
    }
    // _bin is a multimap or something
};
票数 2
EN

Stack Overflow用户

发布于 2011-07-19 08:42:21

find_ifbind2nd以及函子的用法来看,似乎您对STL和一些高级C++概念相当了解;然而,您所要做的似乎是过度工程。虽然我不能完全理解您想要做什么,但是您似乎可以完全取消模板,只使用一个类(用不同的值实例化)和方法参数。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6744365

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档