As continue of thread Compare of std::function with lambda
I have problem with capture this to lambda - and compare after that with "correct callback".
#include <iostream>
#include <functional>
using namespace std;
//////////////////////////////////////////////////////////////////////////
class IFoo
{
public:
virtual void onAppStarted( int, int ) = 0;
};
//////////////////////////////////////////////////////////////////////////
template <typename T>
struct FunctionTypeDeduction;
template<class ClassType, class ReturnType, class... Args>
struct FunctionTypeDeduction< ReturnType( ClassType::* )( Args... ) >
{
using type = ReturnType( *)( Args... );
using functorType = std::function<ReturnType( Args... ) >;
};
//////////////////////////////////////////////////////////////////////////
class SubcribeSystem
{
public:
using tSomeMethodType = FunctionTypeDeduction< decltype( &IFoo::onAppStarted ) >::type;
using tSomeMethodCallback = FunctionTypeDeduction< decltype( &IFoo::onAppStarted ) >::functorType;
public:
void subribeOnSomeMethod( const tSomeMethodCallback& arr )
{
arr( 3, 19 );
}
};
#define SUBCRIBE_FOR_SOMEMETHOD( eventsObj, lambda ) \
do \
{ \
SubcribeSystem::tSomeMethodType const func_ptr = lambda; \
eventsObj.subribeOnSomeMethod( lambda ); \
} \
while(false);
//////////////////////////////////////////////////////////////////////////
class Bar
{
public:
void fn( SubcribeSystem& events )
{
auto onAppStart = []( int width, int height )
{
cout << width << " " << height << endl;
};
auto onAppStart2 = []( bool width, int height )
{
cout << width << " " << height << endl;
};
auto onAppStart3 = [this]( int width, int height )
{
cout << width << " " << height << endl;
someOtherMethod( width );
};
SUBCRIBE_FOR_SOMEMETHOD( events, onAppStart ); // expect all ok
//SUBCRIBE_FOR_SOMEMETHOD( events, onAppStart2 ); // expect error cause bool first param
SUBCRIBE_FOR_SOMEMETHOD( events, onAppStart3 ); // expect all ok, but not !!!
}
void someOtherMethod( int x )
{
cout << "processed callback " << x << endl;
}
};
int main()
{
Bar bar;
SubcribeSystem sub;
bar.fn( sub );
}
In your macro you have
SubcribeSystem::tSomeMethodType const func_ptr = lambda;
Where SubcribeSystem::tSomeMethodType is a
FunctionTypeDeduction< decltype( &IFoo::onAppStarted ) >::type
which is a function pointer. So you are trying to convert the lambda into a function pointer. Unfortunately a lambda that captures, which onAppStart3 does, cannot be converted to a function pointer.
The first two lambdas work as they do not capture so they have an implicit function pointer conversion operator.
Related
I am creating an extended (i.e. __device__) lambda in CUDA (see e.g. here) and it is supposed to capture a variable (here, a simple double value = 3;).
It compiles, but running it, I get an invalid memory access error and I don't understand why.
Changing the variable to static const double value = 3 fixes the problem, as it is no longer captured (though I don't understand how it is still available inside the lambda).
Question1: how can I correctly capture host variables in a CUDA extended lambda?
Question2: why is this code not working?
I tried this on Ubuntu 16, both with CUDA 8 and 10.
MWE Code
Compiled with nvcc mwe_lambda.cu -o mwe_lambda --std=c++11 -lineinfo -arch=sm_60 --expt-relaxed-constexpr --expt-extended-lambda
Note in particular the lambda, which should capture by copy.
The managed_allocator etc. are just in order to use managed memory and print the CUDA error.
#include <cuda.h>
#include <cuda_runtime.h>
#include <vector>
#include <iostream>
#include <string>
static void CudaHandleError( cudaError_t err, const char *file, int line, const std::string & function)
{
if (err != cudaSuccess)
{
std::cerr << std::string(cudaGetErrorString( err )) << " " << file << " " << line << " " << function << std::endl;
}
}
#define CU_HANDLE_ERROR( err ) (CudaHandleError( err, __FILE__, __LINE__, __func__ ))
#define CU_CHECK_ERROR( ) (CudaHandleError( cudaGetLastError(), __FILE__, __LINE__, __func__ ))
#define CU_CHECK_AND_SYNC( ) CU_CHECK_ERROR(); CU_HANDLE_ERROR( cudaDeviceSynchronize() )
template<class T>
class managed_allocator : public std::allocator<T>
{
public:
using value_type = T;
template<typename _Tp1>
struct rebind
{
typedef managed_allocator<_Tp1> other;
};
value_type* allocate(size_t n)
{
value_type* result = nullptr;
CU_HANDLE_ERROR( cudaMallocManaged(&result, n*sizeof(value_type)) );
return result;
}
void deallocate(value_type* ptr, size_t)
{
CU_HANDLE_ERROR( cudaFree(ptr) );
}
managed_allocator() throw(): std::allocator<T>() { } //fprintf(stderr, "Hello managed allocator!\n"); }
managed_allocator(const managed_allocator &a) throw(): std::allocator<T>(a) { }
template <class U>
managed_allocator(const managed_allocator<U> &a) throw(): std::allocator<T>(a) { }
~managed_allocator() throw() { }
};
template<typename T>
using field = std::vector<T, managed_allocator<T>>;
// vf[i] = f()
template<typename A, typename F>
__global__ void cu_set_lambda(A * vf, const F & f, int N)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if(idx < N)
{
vf[idx] = f();
}
}
int main()
{
std::cerr << "started" << std::endl;
{
field<double> vf(10, 0);
double value = 3;
auto lambda = [=] __device__ ()
{
return value;
};
auto n = vf.size();
cu_set_lambda<<<(n+1023)/1024, 1024>>>(vf.data(), lambda, n);
CU_CHECK_AND_SYNC();
std::cerr << vf[0] << " " << vf[1] << std::endl;
}
std::cerr << "finished" << std::endl;
}
You need to pass the lambda by value, as the variables captured by value in the lambda will not be available in device when you pass the lambda by reference.
__global__ void cu_set_lambda(A * vf, const F f, int N)
^^^^^^^
If you pass the lambda by value, the object (and its internals) will be copied to the kernel.
I tried to create a function template that would call a member function in an object, specified by the template parameter, but I failed. Now I have multiple functions that differ only very slightly:
static void resize_callback(raw_resource* ptr, int width, int height)
{
owner* instance = static_cast<owner*>(get_owner(ptr));
assert(instance != nullptr);
instance->on_resize(width, height);
}
static void focus_callback(raw_resource* ptr, bool state)
{
owner* instance = static_cast<owner*>(get_owner(ptr));
assert(instance != nullptr);
instance->on_focus(state);
}
static void other_callback(raw_resource* ptr, type1 arg1, type2 arg2, type3 arg3)
{
owner* instance = static_cast<owner*>(get_owner(ptr));
assert(instance != nullptr);
instance->on_other(arg1, arg2, arg3);
}
...
Each raw_resource has exactly one owner, where owner is a wrapper around raw_resource. The callbacks are fed to a low level C library that doesn't know about owners, but only about raw_resources, so they must take a raw_resource*, that a pointer to them (callbacks) has the appropriate type. The operations in the callbacks need to use the owner objects however, so they retrieve them through get_owner().
How could I make a general function template out of these that would avoid code duplication? I need instantiations of this template to be convertible to appropriate function pointers that will be compatible with their current signatures, so they can be given to the low level C library.
You could use a parameter pack:
template <typename Func, typename... Types>
static void callback(raw_resource* ptr, Func func, Types... args)
{
owner* instance = static_cast<window*>(get_owner(ptr));
assert(instance != nullptr);
(instance->*func)(args...);
}
You might want to pass Types differently.
Used like:
callback(someptr, &owner::on_resize, width, height);
If you have C++17 available you could use std::invoke instead of the ->* syntax.
As the number of arguments in each member function call is different then you can use the following approach
#include <iostream>
struct A
{
static void swap( int *x, int *y )
{
int tmp = *x;
*x = *y;
*y = tmp;
}
void set( bool b )
{
this->b = b;
}
bool b;
};
template <typename ...Args>
void operation( A *ptr, Args ... args )
{
if constexpr( sizeof...( args ) == 1 )
{
ptr->set( args... );
}
else if constexpr( sizeof...( args ) == 2 )
{
ptr->swap( args... );
}
}
int main()
{
A a = { false };
operation( &a, true );
std::cout << "a.b = " << a.b << '\n';
int x = 10; int y = 20;
std::cout << "x = " << x << ", y = " << y << '\n';
operation( &a, &x, &y );
std::cout << "x = " << x << ", y = " << y << '\n';
}
The program output is
a.b = 1
x = 10, y = 20
x = 20, y = 10
I have a class
class MyClass{
public:
int var_x;
int var_y;
int var_z;
}
Then a file.txt:
var_y
var_z
In the main I want to be able to get the address of each variable in file.txt:
int main()
{
MyClass *obj;
obj = new MyClass();
std::vector<std::string>> varList = readFile("file.txt");
// I need generic code that would do the following:
// But the class can have any number (or named) variables
// And the text file can have any subset of the variables
std::cout << "var_y " << &(obj->var_y) << std::endl;
std::cout << "var_y " << &(obj->var_z) << std::endl;
delete obj;
return 0;
// Pseudo code would be
for var in varList:
addr = get_addr_from_string(var)
}
using Gettor = std::function< std::any(void*) > get_ptr;
template<class T>
struct ReflectedClass {
static std::unordered_map<std::string, Gettor> members;
template<class U>
static U* get( T* t, const char* name ) {
auto it = members.find(name);
if (it == members.end()) return nullptr;
std::any a = it->second( t );
U** ptr = std::any_cast<U*>(&a);
if (!ptr) return nullptr;
return *ptr;
}
};
#define TO_STR2(X) ##X
#define TO_STR(X) TO_STR2(X)
#define REFLECTED_MEMBER( CLASS, NAME ) \
ReflectedClass<CLASS>::members[ TO_STR(NAME) ] = \
[]( void* ptr )->std::any { \
return std::addressof( (CLASS*)(ptr)->NAME ); \
}
Then simply do
REFLECTED_MEMBER(MyClass, var_x )
REFLECTED_MEMBER(MyClass, var_y )
REFLECTED_MEMBER(MyClass, var_z )
and you can call
MyClass foo;
int* ptr = ReflectedClass<MyClass>::get<int>( &foo, "var_x" );
and it returns a pointer to foo.var_x.
This is a bad idea, don't do it.
In my callback system I want to store std::function (or something else) with varying arguments.
Example:
I want to call void()
I want to call void(int, int)
I want 1) and 2) to be stored in the same variable and choose what to call in actuall call
FunctionPointer f0;
FunctionPointer f2;
f0();
f2(4, 5);
Is it possible to do something like this? Or I have to create several "FuntionPointer" templates based on input arguments count.
EDIT
Is it possible to utilize std::bind somehow for this task? With std::bind I can have std::function<void()> f = std::bind(test, 2, 5);
EDIT 2
Practical use case: I have a trigger system and I want to assign funtion pointers to actions, so when action happen, function is called.
Pseudo-code sample:
structure Trigger
{
Function f;
}
Init:
Trigger0.f = pointer to some function ()
Trigger1.f = pointer to some function (a, b)
Input:
Find Trigger by input
if (in == A) Trigger.f();
else Trigger.f(10, 20)
or if possible
Input:
Find Trigger by input
if (in == A) f = bind(Trigger.f);
else f = bind(Trigger.f, 10, 20);
f()
std::function<void()> and std::function<void(int, int)> are two absolutely distinct types. You need some sort of union functionality (or polymorphism) to store an object of an unknown type.
If you can use Boost, you could easily do this with boost::variant:
// Declaration:
boost::variant<std::function<void()>, std::function<void(int, int)> > f;
// Calling, explicit:
if (fContainsNullary()) {
boost::get<std::function<void()>>(f)();
} else {
boost::get<std::function<void(int, int)>>(f)(4, 5);
}
It is up to you to provide the logic of fContainsNullary(). Alternatively, you can use the variant's own stored knowledge of value type by using a visitor:
struct MyVisitor : boost::static_visitor<void>
{
result_type operator() (const std::function<void()> &a) {
a();
}
result_type operator() (const std::function<void(int, int)> &a) {
a(4, 5);
}
};
// Calling, via visitor:
boost::apply_visitor(MyVisitor(), f);
If Boost is not an option, you can hand-craft a suitable union for much the same purpose.
The following solution might work for you (I'm not sure that the code is absolutely correct here):
Create a wrapper for std::function with virtual destructor to enable using dynamic cast
class function_wrapper_base
{
virtual ~function_wrapper_base();
}
template <class... Args>
class function_wrapper
: public function_wrapper_base
{
public:
std::function<void, Args...> f;
...
};
Then create a class variant_function_holder
class variant_function_holder
{
std::unique_ptr<function_wrapper_base> f;
...
template <class... Args>
void operator()(Args&&... args)
{
function_wrapper<std::decay<Args>::type...> * g = dynamic_cast<function_wrapper<std::decay<Args>::type...>>(f.get());
if (g == nullptr)
{
// ToDo
}
g->f(std::forward<Args>(args)...);
}
};
Well, if you can use RTTI, you can define a MultiFuncObject like this, and you can easily bind other functions. Also, you can easily call them. But unfortunately, this approach only works for a limited number of arguments. But actually boost::bind also supports limited number of arguments (by default 9). So you can extend this class to satisfy your needs.
Before giving you the source of MultiFuncObject, I want to show you how you can use it. It takes an template argument to be used as return type. You can bind new functions with += operator. With some template magic, the class distinguishes differences between bound functions with same count of arguments with at least one different argument type.
You need C++11, because MultiFuncObject uses std::unordered_map and std::type_index.
Here is usage:
#include <iostream>
using namespace std;
void _1() {
cout << "_1" << endl;
}
void _2(char x) {
cout << "_2" << " " << x << endl;
}
void _3(int x) {
cout << "_3" << " " << x << endl;
}
void _4(double x) {
cout << "_4" << " " << x << endl;
}
void _5(int a, int b) {
cout << "_5" << " " << a << " " << b << endl;
}
void _6(char a, int b) {
cout << "_6" << " " << a << " " << b << endl;
}
void _7(int a, int b, int c) {
cout << "_7" << " " << a << " " << b << " " << c << endl;
}
int main() {
MultiFuncObject<void> funcs;
funcs += &_1;
funcs += &_2;
funcs += &_3;
funcs += &_4;
funcs += &_5;
funcs += &_6;
funcs += &_7;
funcs();
funcs('a');
funcs(56);
funcs(5.5);
funcs(2, 5);
funcs('q', 6);
funcs(1, 2, 3);
return 0;
}
I hope this is close to what you want. Here is the source of MultiFuncObject:
#include <typeinfo>
#include <typeindex>
#include <unordered_map>
using namespace std;
template <typename R>
class MultiFuncObject {
unordered_map<type_index, void (*)()> m_funcs;
public:
MultiFuncObject<R> operator +=( R (* f)() ) {
m_funcs[typeid( R() )] = (void (*)()) f;
return *this;
}
template <typename A1>
MultiFuncObject<R> operator +=( R (* f)(A1) ) {
m_funcs[typeid( R(A1) )] = (void (*)()) f;
return *this;
}
template <typename A1, typename A2>
MultiFuncObject<R> operator +=( R (* f)(A1, A2) ) {
m_funcs[typeid( R(A1, A2) )] = (void (*)()) f;
return *this;
}
template <typename A1, typename A2, typename A3>
MultiFuncObject<R> operator +=( R (* f)(A1, A2, A3) ) {
m_funcs[typeid( R(A1, A2, A3) )] = (void (*)()) f;
return *this;
}
R operator()() const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R() ));
if (it != m_funcs.end()) {
R (*f)() = ( R (*)() )(it->second);
(*f)();
}
}
template <typename A1>
R operator()(A1 a1) const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1) ));
if (it != m_funcs.end()) {
R (*f)(A1) = ( R (*)(A1) )(it->second);
(*f)(a1);
}
}
template <typename A1, typename A2>
R operator()(A1 a1, A2 a2) const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1, A2) ));
if (it != m_funcs.end()) {
R (*f)(A1, A2) = ( R (*)(A1, A2) )(it->second);
(*f)(a1, a2);
}
}
template <typename A1, typename A2, typename A3>
R operator()(A1 a1, A2 a2, A3 a3) const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1, A2, A3) ));
if (it != m_funcs.end()) {
R (*f)(A1, A2, A3) = ( R (*)(A1, A2, A3) )(it->second);
(*f)(a1, a2, a3);
}
}
};
It stores different function prototypes using std::unordered_map with keys of std::type_index and values of void (*)(). When needed, the correct function is retrieved using that map.
Here is the working example
C++11 to the rescue!
If you can generalize your function to a functor object taking no arguments, then you can call it with any lambda.
#include <iostream>
using namespace std;
template <class F>
void call_it(F&& f)
{
f();
}
int main()
{
int x = 50, y = 75;
call_it([] () { cout << "Hello!\n"; });
call_it([x,y] () { cout << x << " + " << y << " = " << x + y << '\n';});
return 0;
}
If std::function is not necessary for you, you can create a proxy class.
class fn_t {
public:
typedef void (*fn_1_t)();
typedef void (*fn_2_t)(int, int);
fn_1_t fn_1;
fn_2_t fn_2;
fn_t operator=(fn_1_t func_1) { fn_1 = func_1; return *this; }
fn_t operator=(fn_2_t func_2) { fn_2 = func_2; return *this; }
void operator()() { (*fn_1)(); }
void operator()(int a, int b) { (*fn_2)(a, b); }
};
#include <iostream>
using namespace std;
void first() {
cout << "first" << endl;
}
void second(int a, int b) {
cout << "second " << a << " : " << b << endl;
}
int main() {
fn_t f;
f = &first;
f = &second;
f();
f(5, 4);
return 0;
}
Class fn_t automatically works with two prototypes you want, assigns automatically needed one, and it can call functions with both prototypes by overlading () operator with appropriate parameters.
You may want to check for validity of function pointers fn_1 and fn_2 but I didn't include this checking for minimality.
The advantage of this is that you only need C++ and not even STL and Boost.
The other answers are fine but I want to show my solution as well.
It's a small header with which you can "elongate" function signatures.
This allows you to do this (extract from the github example):
int foo_1p(int a);
int foo_2p(int a, int b);
int foo_3p(int a, int b, int c);
int foo_4p(int a, int b, int c, int d);
int foo_5p(int a, int b, int c, int d, int e);
int foo_6p(int a, int b, int c, int d, int e, int f);
int foo_7p(int a, int b, int c, int d, int e, int f, std::string g);
...
int main()
{
std::unordered_map<std::string, std::function<int(int, int, int, int, int, int, std::string)>> map;
map["foo_1p"] = ex::bind(foo_1p, ph, ph, ph, ph, ph, ph);
map["foo_2p"] = ex::bind(foo_2p, ph, ph, ph, ph, ph);
map["foo_3p"] = ex::bind(foo_3p, ph, ph, ph, ph);
map["foo_4p"] = ex::bind(foo_4p, ph, ph, ph);
map["foo_5p"] = ex::bind(foo_5p, ph, ph);
map["foo_6p"] = ex::bind(foo_6p, ph);
map["foo_7p"] = foo_7p;
for (const auto& f : map)
{
std::cout << f.first << " = " << f.second(1, 1, 1, 1, 1, 1, "101") << std::endl;
}
}
The goal of the code below is to implement a histogram where the bucket limits are 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. With the repeated rest() calls, the count of the final bucket (values >= 15) is printed.
However, when the final line of main() is uncommented, g++ 4.7.1 generates a compiler error that bucket_limit_entry<0u> and bucket_count_entry<0u> are incomplete.
Any advice on how to get the convenience functions bucket_limit<3> to compile, since the repeated rest() calls work?
Not really sure what's going on. Changing the index type to int and making the termination case -1 instead of 0 didn't work.
Here's histogram.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);
}
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, but First can only match one int).
So you need to add an additional template for the case where you've run out of limits:
template<>
struct bucket_limit_entry<0>
When you do that, you'll find that histogram<>::limit() is undefined, but you can easily fix that.
You'll need to do the same with bucket_count_entry, except that histogram<>::count() is defined.
The fact that you can't just define template<int...Limits> struct bucket_limit_entry<0, Limits...> {...} is a bit odd. The problem, as I understand it, is that both "Index is 0" and "Limits... has at least one element", are restrictions on the general template, and there is no arbitrary ordering between them. Consequently, template<int...Limits> struct X<0, Limits...> and template<unsigned index, int First, int...Rest> struct X<index, First, Rest...> are not ordered by the partial ordering for template specialization, and when both of them apply, you end up with an ambiguity.
But it seems to me that there is a simpler solution, since you can let the type of the histogram_tuple just be deduced:
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);
}