2016-10-04 46 views
0

构建可执行特定任务的可变参数函数时遇到了问题。对于我的特定示例,我使用的是2×2矩阵,但您可以想象我的问题可以概括为许多数据类型。另外,就我的例子而言,“眼睛”是2x2单位矩阵。Kronecker产品的可变参数函数

好了,我想建立一个可变参数的函数f的输入端可能是(以得到3个实施例):

f(Y, 2, Z, 5, X, 3) 
f(X, 4) 
f(X, 2, Y, 1) 

,其中X,Y,Z是矩阵,和数量是正整数。它应该返回下面的伪代码克罗内克产品,分别为:

KroneckerProduct(eye, Y, X, eye, Z) 

KroneckerProduct(eye, eye, eye, X) 

KroneckerProduct(Y, X) 

所以基本上它在通过下面的基质中的int指定的克罗内克积位置应用矩阵,并填写身份之间的矩阵英寸

由于我对variadic函数没有经验,所以我没有太多的了解它。我最大的问题是越来越可变参数函数的“递归”一步我需要什么(见末注释):

template<typename M, typename I, typename... Args> 
arma::mat f(M matrix, I position, Args... args) 
{ 
    std::vector<arma::mat> matrixList; 

    while(position > matrixList.size()) 
    { 
     matrixList.push_back(eye<arma::mat>(2,2)); 
    } 

    matrixList(position-1) = matrix; 

    //Up until here, it's satisfied the first pair of arguments. 
    //However, if I call f(args...) now, it'll just re-initialize matrixList 
} 

有没有办法,我缺少一个解决方法吗?

+0

这是完全一样的解决方法是“正常”的递归函数:) – Rakete1111

+0

你是在暗示声明matrixList后的东西要放在另一个函数g(标准::矢量&matrixList,ARGS ... ),并在g内进行递归?就我所了解的可变参数模板而言,由于g在参数前面只有一个参数...,参数是不是只能一次一个解压缩?我需要他们一次解包两个,以便让作业变得有意义。 – user2520385

回答

2

我不知道你将如何计算返回值(我还不明白那种数学),但是如果你从最终的matrixList中计算出来,你可以对函数做一个包装:

template<typename... Args> 
arma::mat calculateSomething(Args&&... args) { 
    std::vector<arma::mat> list; 
    f(list, std::forward<Args...>(args...)); //First argument for recursion 

    //Calculate return value 
    return return_value; 
}; 

而且f应该是这样的:

//Default case with just 1 argument 
void f(std::vector<arma::mat>&) {} 

template<typename M, typename I, typename... Ts> 
void f(std::vector<arma::mat>& matrixList, M matrix, I position, Ts... args) 
{ 
    while(position > matrixList.size()) 
    { 
     matrixList.push_back(eye<arma::mat>(2,2)); 
    } 

    //This is not valid syntax, no idea what you are trying to do here 
    //matrixList(position-1) = matrix; 

    //recursive call 
    f(matrixList, args...); 
} 
+0

谢谢,这让它工作,但我仍然不完全了解如何转发工作...我需要阅读它。我会发布完成的代码片段。 – user2520385

1

建立关Rakete1111的建议,这是代码,我想要它工作。它生成k-量子位Heisenberg interactions

#include <iostream> 
#include <armadillo> 

const arma::cx_mat eye = "(1,0) (0,0); (0,0) (1,0)"; 
const arma::cx_mat sx = "(0,0) (1,0); (1,0) (0,0)"; 
const arma::cx_mat sy = "(0,0) (0,-1); (0,1) (0,0)"; 
const arma::cx_mat sz = "(1,0) (0,0); (0,0) (-1,0)"; 

void ArgsToMatrixList(std::vector<arma::cx_mat>&) {} 

template<typename M, typename I, typename... Ts> 
void ArgsToMatrixList(std::vector<arma::cx_mat>& matrixList, M matrix, I position, Ts... args) 
{ 
    while(position > matrixList.size()) 
    { 
     matrixList.push_back(eye); 
    } 

    matrixList[position - 1] = matrix; 

    ArgsToMatrixList(matrixList, args...); 
} 

template<typename... Args> 
arma::cx_mat J(Args&&... args) 
{ 
    std::vector<arma::cx_mat> list; 

    ArgsToMatrixList(list, std::forward<Args>(args)...); //First argument for recursion 

    //Calculate return value 

    arma::cx_mat return_value = list.front(); 
    for(int i = 1; i < list.size(); ++i) 
    { 
     return_value = arma::kron(return_value, list[i]); 
    } 

    return return_value; 
} 


int main(int argc, const char * argv[]) { 

    arma::cx_mat example = J(sx, 1, sy, 2, sz, 3); 
    std::cout << example << std::endl; 

    return 0; 
}