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> が不完全であるというコンパイラ エラーが発生します。

繰り返しの rest() 呼び出しが機能するため、便利な関数bucket_limit<3>をコンパイルする方法に関するアドバイスはありますか?

何が起こっているのかよくわかりません。インデックス タイプを int に変更し、終了ケースを 0 ではなく -1 にすると機能しませんでした。

ヒストグラム.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何にも一致しませんが、First1 つのみに一致できますint)。

したがって、制限を使い果たした場合に備えて、追加のテンプレートを追加する必要があります。

template<>
struct bucket_limit_entry<0>

これを行うと、それが未定義であることがわかりますhistogram<>::limit()が、簡単に修正できます。

histogram<>::count()定義されていることを除いて、bucket_count_entry で同じことを行う必要があります。

定義できないという事実template<int...Limits> struct bucket_limit_entry<0, Limits...> {...}は少し奇妙です。私が理解している問題は、「Indexが0である」と「Limits...少なくとも1つの要素がある」の両方が一般的なテンプレートの制限であり、それらの間に任意の順序がないことです。したがって、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 に答える