Is it possible for something like this to exist?
template<int Channel>
void deduce_mask(Matrix const &src, int mask[])
{
//I hope i could become a constant and the compiler would unroll the loop at compile time
for(int i = Channel; i != -1; --i)
{
//mapper is a helper class which translate two and three dimension into one dimension index
//constexpr makes it possible to find out the index at compile time
mask[mapper(0, 1, i)] = src(row - 1, col)[i];
mask[mapper(1, 1, i)] = src(row, col)[i];
mask[mapper(2, 1, i)] = src(row + 1, col)[i];
}
}
instead of
template<int Channel>
class deduceMask
{
public:
static void deduce_mask(matrix const &src, int mask[]);
};
template<int Channel>
void deduce_mask(matrix const &src, int mask[])
{
mask[mapper(0, 1, Channel)] = src(row - 1, col)[Channel];
mask[mapper(1, 1, Channel)] = src(row, col)[Channel];
mask[mapper(2, 1, Channel)] = src(row + 1, col)[Channel];
deduceMask<Channel - 1>::deduce_mask(src, mask);
}
template<>
class deduceMask<-1>
{
public:
static void deduce_mask(matrix const &src, int mask[])
{
}
};
The second solution is the only solution I could come up of when I want the compiler to figure out the result at compile time. Do I have an easy way to make the “i” become constant value likethe metaprogramming solution? For me, a simple for loop is much more easier to work with rather than the metaprogramming version.
Template metaprogramming in C++ is pure functional programming, and in pure functional programming you don’t get to use loops like for or while and you don’t get to have any mutable data at all. All you have is recursion. To make working with recursion easier, you need to rise abstraction level a bit. The recursive code that you have is fine, but the iteration and work can be split apart:
Now that you have this meta-function, you can write your deduce_mask function like this:
Visual C++ 2012 with /Ob1 command line switch compiles this code into this:
If you can’t use lambda functions, you need to write a functor. Functor has one advantage over lambda function – you can specify a calling convention (if you don’t mind doing that). If the operator() of the functor has
__fastcallcalling convention then you will seemov edx, xinstead ofpush xin the assembler code.