0

下面代码的目标是实现一个直方图,其中桶限制是模板参数:

#include <iostream>
#include <limits>
#include "histogram.h"


int main ( int argc, char* argv[] )
{
//histogram_tuple<5,10,15,std::numeric_limits<int>::max()> histogram;
histogram_tuple<5,10,15> histogram;

histogram.count ( 9 );
histogram.count ( 10 );
histogram.count ( 11 );
histogram.count ( 15 );

std::cout << sizeof ( histogram ) << std::endl;
std::cout << '<' << histogram.limit() << ' ' << histogram.count() << ", "
<< '<' << histogram.rest().limit() << ' ' << histogram.rest().count() << ", "
<< '<' << histogram.rest().rest().limit() << ' ' << histogram.rest().rest().count() << ", "
<< ' ' << histogram.rest().rest().rest().count()
<< std::endl;

std::cout << "====" << std::endl;

std::cout << '<' << bucket_limit<0>(histogram) << ':'
<< bucket_count<0>(histogram) << std::endl;
std::cout << '<' << bucket_limit<1>(histogram) << ':'
<< bucket_count<1>(histogram) << std::endl;
std::cout << '<' << bucket_limit<2>(histogram) << ':'
<< bucket_count<2>(histogram) << std::endl;
// std::cout << '<' << bucket_limit<3>(histogram) << ':'
//           << bucket_count<3>(histogram) << std::endl;
}

以上工作正常。通过重复的 rest() 调用,最终存储桶的计数(值 >= 15)被打印出来。

但是,当 main() 的最后一行未注释时,g++ 4.7.1 会生成一个编译器错误,即 bucket_limit_entry<0u> 和 bucket_count_entry<0u> 不完整。

关于如何让便利函数 bucket_limit<3> 编译的任何建议,因为重复的 rest() 调用有效?

不太清楚发生了什么。将索引类型更改为 int 并使终止案例 -1 而不是 0 不起作用。

这是直方图.h:

#pragma once

template <int ... Limits>
class histogram_tuple;

template<>
class histogram_tuple<>
{
int cnt_;
public:
histogram_tuple<>() :
cnt_ ( 0 )
{
}

void count ( int value )
{
++cnt_;
}

int count() const
{
return cnt_;
}
};


template <int First, int ... Rest>
class histogram_tuple <First,Rest...> :
private histogram_tuple<Rest...>
{
static const int limit_ = First;
int cnt_;
public:
histogram_tuple <First,Rest...>() :
cnt_ ( 0 )
{ }

int limit() const { return limit_; }

void count ( int value )
{
if ( value < limit_ )
++cnt_;
else
rest().count ( value );
}

int count() const
{
return cnt_;
}

const histogram_tuple<Rest...>& rest() const
{
return *this;
}

histogram_tuple<Rest...>& rest()
{
return *this;
}
};


template <unsigned index, int ... Limits>
struct bucket_count_entry;

template <int First, int ... Limits>
struct bucket_count_entry<0,First,Limits...>
{
static int value(histogram_tuple<First,Limits...> const& histogram)
{
return histogram.count();
}
};

template <unsigned index,int First, int ... Limits>
struct bucket_count_entry<index,First,Limits...>
{
static int value(histogram_tuple<First,Limits...> const& histogram)
{
return bucket_count_entry<index-1,Limits...>::value(histogram.rest());
}
};

template <unsigned index,int ... Limits>
int bucket_count( histogram_tuple<Limits...> const& histogram )
{
return bucket_count_entry<index,Limits...>::value(histogram);
}


template <unsigned index, int ... Limits>
struct bucket_limit_entry;

template <int First, int ... Limits>
struct bucket_limit_entry<0,First,Limits...>
{
static int value(histogram_tuple<First,Limits...> const& histogram)
{
return histogram.limit();
}
};

template <unsigned index,int First, int ... Limits>
struct bucket_limit_entry<index,First,Limits...>
{
static int value(histogram_tuple<First,Limits...> const& histogram)
{
return bucket_limit_entry<index-1,Limits...>::value(histogram.rest());
}
};

template <unsigned index,int ... Limits>
int bucket_limit( histogram_tuple<Limits...> const& histogram )
{
return bucket_limit_entry<index,Limits...>::value(histogram);
}
4

1 回答 1

1
template <int First, int ... Limits>
bucket_limit_entry<0,First,Limits...>

不匹配

bucket_limit_entry<0>

因为First不会匹配任何东西。(...Limits不匹配,但First只能匹配一个int)。

因此,您需要为超出限制的情况添加一个额外的模板:

template<>
struct bucket_limit_entry<0>

当你这样做时,你会发现它histogram<>::limit()是未定义的,但你可以很容易地修复它。

您需要对 bucket_count_entry 执行相同的操作,但histogram<>::count()已定义。

您不能只定义这一事实template<int...Limits> struct bucket_limit_entry<0, Limits...> {...}有点奇怪。据我了解,问题是“Index为0”和“Limits...至少有一个元素”都是对通用模板的限制,并且它们之间没有任意顺序。因此,template<int...Limits> struct X<0, Limits...>并且template<unsigned index, int First, int...Rest> struct X<index, First, Rest...>没有按模板专业化的部分排序进行排序,并且当它们都适用时,您最终会产生歧义。

但在我看来,有一个更简单的解决方案,因为您可以histogram_tuple推导出刚刚的类型:

template<unsigned Index> struct bucket_limit_entry {
    template<typename Hist>
    static int value(Hist const& histogram) {
        return bucket_limit_entry<Index-1>::value(histogram.rest());
    }
};

template<> struct bucket_limit_entry<0> {
    template<typename Hist>
    static int value(Hist const& histogram) {
        return histogram.limit();
    }
};

template<unsigned index, typename Hist>
int bucket_limit(Hist const& histogram ) {
    return bucket_limit_entry<index>::value(histogram);
}
于 2013-02-11T05:29:55.960 回答