問題描述
這樣的東西有可能存在嗎?
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];
}
}
代替
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[])
{
}
};
當我希望編譯器在編譯時找出結果時,第二個解決方案是我能想到的唯一解決方案.我是否有一種簡單的方法可以像元編程解決方案一樣使i"成為常量值?對我來說,一個簡單的 for 循環比元編程版本更容易使用.
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.
推薦答案
C++ 中的模板元編程是純函數式編程,而在純函數式編程中,您無法使用 for 或 while 之類的循環,也無法使用根本沒有任何可變數據.你所擁有的只是遞歸.為了更容易地使用遞歸,您需要稍微提高抽象級別.您擁有的遞歸代碼很好,但迭代和工作可以分開:
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:
template <int First, int Last>
struct static_for
{
template <typename Fn>
void operator()(Fn const& fn) const
{
if (First < Last)
{
fn(First);
static_for<First+1, Last>()(fn);
}
}
};
template <int N>
struct static_for<N, N>
{
template <typename Fn>
void operator()(Fn const& fn) const
{ }
};
既然你有了這個元函數,你可以像這樣編寫你的 deduce_mask 函數:
Now that you have this meta-function, you can write your deduce_mask function like this:
template<int Channel>
void deduce_mask(Matrix const &src, int mask[])
{
static_for<0, Channel>()([&](int i)
{
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];
});
}
帶有/Ob1 命令行開關的 Visual C++ 2012 將此代碼編譯為:
Visual C++ 2012 with /Ob1 command line switch compiles this code into this:
push 0
call <lambda_7588286c1d4f3efe98a2e307bd757f8e>::operator() (010C1270h)
push 1
call <lambda_7588286c1d4f3efe98a2e307bd757f8e>::operator() (010C1270h)
push 2
call <lambda_7588286c1d4f3efe98a2e307bd757f8e>::operator() (010C1270h)
push 3
call <lambda_7588286c1d4f3efe98a2e307bd757f8e>::operator() (010C1270h)
push 4
call <lambda_7588286c1d4f3efe98a2e307bd757f8e>::operator() (010C1270h)
...
如果你不能使用 lambda 函數,你需要寫一個函子.與 lambda 函數相比,Functor 有一個優勢——您可以指定調用約定(如果您不介意這樣做).如果函子的 operator() 具有 __fastcall
調用約定,那么您將在匯編代碼中看到 mov edx, x
而不是 push x
.
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 __fastcall
calling convention then you will see mov edx, x
instead of push x
in the assembler code.
這篇關于是否可以在 C++ 中開發靜態 for 循環?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!