/*!
* @file GenericImage_typeDispatch.cpp
* @brief
* @author vectra
* @date 16/05/19
*/
#include <iostream>
#include <vector>
#include <exception>
#include <array>
using namespace std;
// =============================================================================
// type helpers
// =============================================================================
template < typename T >
void showType(T var)
{ throw; }
template <>
void showType(double var)
{ cout << "double"; }
template <>
void showType(int var)
{ cout << "int"; }
template <>
void showType(float var)
{ cout << "float"; }
// =============================================================================
// dummy typed image class (implemented likewise by many real image libs)
// =============================================================================
class Image
{
public:
enum class Type
{
Float64,
Float32,
Int32,
} type_;
std::size_t voxel_count_;
void *data_ptr_ = nullptr;
Image()
{}
void
allocate(Image::Type t, size_t voxel_count)
{
type_ = t;
voxel_count_ = voxel_count;
switch (t)
{
case Image::Type::Float64:
data_ptr_ = static_cast<void *>(new double[voxel_count]);
break;
case Image::Type::Int32:
data_ptr_ = static_cast<void *>(new int[voxel_count]);
break;
default:
throw;
}
}
void
set_data(Image::Type t, void *data)
{
if ( data_ptr_ != nullptr ) throw;
type_ = t;
data_ptr_ = data;
}
};
// =============================================================================
// Dispatcher mother, where all ropes are hidden from the user
// =============================================================================
template < class Derived >
class ExecutorMother
{
public:
Image *img_ = nullptr;
ExecutorMother(Image *img) : img_(img)
{}
// This code compiles but does not work as expected (int filter function always called)
template < class ... ArgsType >
void
operator()(ArgsType ... arguments)
{
if ( ExecutorMother::img_ -> data_ptr_ == nullptr ) throw;
Derived &derived = static_cast<Derived &>(*this);
switch (ExecutorMother::img_ -> type_)
{
case Image::Type::Float64:
{
derived . filter_function(arguments ...);
//derived . filter_function<double>(arguments ...); // auugh! why!!
break;
}
case Image::Type::Float32:
{
derived . filter_function(arguments ...);
//derived . filter_function<float>(arguments ...); // auugh! why!!
break;
}
case Image::Type::Int32:
{
derived . filter_function(arguments ...);
//derived . filter_function<int>(arguments ...); // auugh! why!!
break;
}
default:
throw;// std::bad_exception;
}
}
};
// =============================================================================
// Dispatcher mother, where all ropes are hidden from the user
// =============================================================================
class CustomDispatcher : public ExecutorMother<CustomDispatcher>
{
public:
CustomDispatcher(Image *img) : ExecutorMother(img)
{}
template < typename ImgDataType >
void
filter_function(ImgDataType trigger_val, int iters, float dummy)
{
ImgDataType *data = static_cast<ImgDataType *>(ExecutorMother::img_ -> data_ptr_);
cout << endl << "Types for filter: ";
showType(data[0]);
cout << " / arg1: ";
showType(trigger_val);
cout << " / arg2: ";
showType(iters);
cout << " / arg3: ";
showType(dummy);
for (size_t i = 0; i < ExecutorMother::img_ -> voxel_count_; i ++)
{
if ( data[i] == trigger_val )
data[i] = data[i] + iters;
}
}
/*
* @brief this code works 100% fine; but would like it hidden in motherclass
*/
/*
template < class ... ArgsType >
void
operator()(ArgsType ... arguments)
{
if ( ExecutorMother::img_ -> data_ptr_ == nullptr ) throw;
switch (ExecutorMother::img_ -> type_)
{
case Image::Type::Float64:
{
filter_function<double>(arguments ...);
break;
}
case Image::Type::Float32:
{
filter_function<float>(arguments ...);
break;
}
case Image::Type::Int32:
{
\
filter_function<int>(arguments ...);
break;
}
default:
throw;// std::bad_exception;
}
}
*/
};
int main()
{
std::array<int, 8> data = {1, 2, 3, - 32768, 5, 6, 7, 8};
Image imgd;
imgd . allocate(Image::Type::Float64, 2 * 4);
Image imgi;
imgi . allocate(Image::Type::Int32, 2 * 4);
CustomDispatcher execd(&imgd);
execd(- 32768, 32000, 3.14);
cout << endl << "double attendu pour type filtre";
CustomDispatcher execi(&imgi);
execi(- 32768, 32000, 3.14);
cout << endl << "int attendu pour type filtre";
return 0;
}