是否可能在c ++中开发静态for循环? [英] Is it possible to develop static for loop in c++?

查看:91
本文介绍了是否可能在c ++中开发静态for循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这样的东西有可能存在吗?

 模板< int Channel> 
void deduce_mask(Matrix const& src,int mask [])
{
//我希望我可以成为一个常量,编译器会在编译时展开循环
for(int i = Channel; i!= -1; --i)
{
// mapper是一个帮助类,它将两维和三维转换为一个维度索引
// constexpr使得可以在编译时找到索引
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) ;
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);
}

模板<>
class deduceMask -1>
{
public:
static void deduce_mask(matrix const& src,int mask [])
{

}
}

第二个解决方案是我想要编译器找出
在编译时的结果。我有一个简单的方法让i成为常量值像
元编程解决方案?对我来说,一个简单的for循环更容易工作,而不是
元编程版本。



对不起,我的英语不好,我希望我能正确解释我的问题。

解决方案

C ++中的模板元编程是纯函数编程,在纯函数编程中,你不能使用循环,如for或while,并且不能有任何可变数据。你所有的都是递归。为了使递归的工作更容易,你需要提高抽象级别。你的递归代码是好的,但是迭代和工作可以分开:

 模板< int首先,int最后> 
struct static_for
{
template< typename Fn>
void operator()(Fn const& fn)const
{
if(First< Last)
{
fn
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函数:

  template< int Channel> 
void deduce_mask(Matrix const& src,int mask [])
{
static_for< 0,Channel>()([&](int i)
{
mask [mapper(1,1,i)] = src(row-col)[i];
mask [ i];
mask [mapper(2,1,i)] = src(row + 1,col)[i];
}使用/ Ob1命令行开关将Visual C ++ 2012编译为: / p>

  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函数有一个优点 - 你可以指定一个调用约定(如果你不介意这样做)。如果函子的operator()具有 __fastcall 调用约定,那么你将看到 mov edx,x ,而不是 push x 在汇编代码中。


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 like the metaprogramming solution?For me, a simple for loop is much more easier to work with rather than the metaprogramming version.

Sorry for my poor English, I hope I explain my problem properly.

解决方案

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

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];    
    });
}

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)  
...

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循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆