Friday, 15 June 2012

c++ - direct access of terminating case of variadic template class works, but convenience class access fails compilation -



c++ - direct access of terminating case of variadic template class works, but convenience class access fails compilation -

the goal of code below implement histogram bucket limits template parameters:

#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; }

the above works fine. repeated rest() calls, count of final bucket (values >= 15) printed.

however, when final line of main() uncommented, g++ 4.7.1 generates compiler error bucket_limit_entry<0u> , bucket_count_entry<0u> incomplete.

any advice on how convenience functions bucket_limit<3> compile, since repeated rest() calls work?

not sure what's going on. changing index type int , making termination case -1 instead of 0 didn't work.

here's histogram.h:

#pragma 1 time 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 { homecoming 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 { homecoming limit_; } void count ( int value ) { if ( value < limit_ ) ++cnt_; else rest().count ( value ); } int count() const { homecoming cnt_; } const histogram_tuple<rest...>& rest() const { homecoming *this; } histogram_tuple<rest...>& rest() { homecoming *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) { homecoming 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) { homecoming bucket_count_entry<index-1,limits...>::value(histogram.rest()); } }; template <unsigned index,int ... limits> int bucket_count( histogram_tuple<limits...> const& histogram ) { homecoming 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) { homecoming 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) { homecoming bucket_limit_entry<index-1,limits...>::value(histogram.rest()); } }; template <unsigned index,int ... limits> int bucket_limit( histogram_tuple<limits...> const& histogram ) { homecoming bucket_limit_entry<index,limits...>::value(histogram); }

template <int first, int ... limits> bucket_limit_entry<0,first,limits...>

won't match

bucket_limit_entry<0>

because first won't match nothing. (...limits matches nothing, first can match 1 int).

so need add together additional template case you've run out of limits:

template<> struct bucket_limit_entry<0>

when that, you'll find histogram<>::limit() undefined, can prepare that.

you'll need same bucket_count_entry, except histogram<>::count() defined.

the fact can't define template<int...limits> struct bucket_limit_entry<0, limits...> {...} bit odd. problem, understand it, both "index 0" , "limits... has @ to the lowest degree 1 element", restrictions on general template, , there no arbitrary ordering between them. consequently, template<int...limits> struct x<0, limits...> , template<unsigned index, int first, int...rest> struct x<index, first, rest...> not ordered partial ordering template specialization, , when both of them apply, end ambiguity.

but seems me there simpler solution, since can allow type of histogram_tuple deduced:

template<unsigned index> struct bucket_limit_entry { template<typename hist> static int value(hist const& histogram) { homecoming bucket_limit_entry<index-1>::value(histogram.rest()); } }; template<> struct bucket_limit_entry<0> { template<typename hist> static int value(hist const& histogram) { homecoming histogram.limit(); } }; template<unsigned index, typename hist> int bucket_limit(hist const& histogram ) { homecoming bucket_limit_entry<index>::value(histogram); }

c++ variadic-templates

No comments:

Post a Comment