C++11 条件数据类型
C++11 conditional data type
我编写了一个有条件地初始化对象的 C++11 函数。考虑以下示例:
arma::mat some_function(bool a, bool b, unsigned long int c) {
if(a) {
if(b) {
arma::sp_mat d(c, c);
} else {
arma::SpMat<short> d(c, c);
}
} else {
if(b) {
arma::mat d(c, c, fill::zeros);
} else {
arma::Mat<short> d(c, c, fill::zeros);
}
}
// Some other computations and a return statement
}
如您所见,我想初始化一个对象 d
,其中 (Armadillo) 数据类型取决于布尔值 a
和 b
。不幸的是,它没有编译,编译器抱怨 d
没有在随后使用的范围内声明。
我发现了关于类似问题的各种讨论。条件初始化显然是在 C++17 中引入的。但是,我需要在此应用程序中使用 C++11。其他建议提及 type_traits
库和 lambda 函数。许多讨论都集中在有条件地指定对象的内容而不是它的数据类型上。由于我对 C++ 还很陌生,所以我不确定如何将这些选项中的任何一个应用于此嵌套条件结构。
您可能需要将通用代码放入一个 template
函数中,该函数可为所有 4 种不同类型实例化。然后,在所有 4 个分支中,调用此模板。编译器将生成 4 个不同的实例化。
template<class F>
arma::mat some_function(bool a, bool b, unsigned long int c, F f) {
if(a) {
if(b) {
arma::sp_mat d(c, c);
return f(d);
}
arma::SpMat<short> d(c, c);
return f(d);
}
if(b) {
arma::mat d(c, c, fill::zeros);
return f(d);
}
arma::Mat<short> d(c, c, fill::zeros);
return f(d);
}
arma::mat some_function(bool a, bool b, unsigned long int c){
return some_function(a, b, c,
[](auto&& d)->arma::mat{
// Some other computations and a return statement
}
);
}
我相信这可以解决您的问题,但需要 c++14。
这里的风格叫做“延续传递风格”;第一个模板创建变量 d
,然后将其传递给您传递给它的函数。然后它 returns 它需要什么函数 returns 当它反过来需要一个 d
.
底部 lambda 中的代码必须能够处理 d
模板函数中可能存在的任何类型,因为它不知道 bool 值是什么。
(如果 bool 值已知,还有其他方法,但通常答案是“如果你知道,并且只有一些有效,为什么 bool 值存在?)
c++14 特性编写起来非常简单,如果您告诉它使用 c++1y(它们的早期预编译器,大多数 c++11 编译器都支持它-C++14 的标准版本)。如果没有,您可以将其替换为:
[](auto&& d)->arma::mat{
// Some other computations and a return statement
}
与
struct some_helper {
template<class M>
arma::mat operator()(M&& m)const {
// Some other computations and a return statement
}
};
在some_function
之外,然后
arma::mat some_function(bool a, bool b, unsigned long int c){
return some_function(a, b, c,
some_helper{}
);
}
在c++14的情况下,如果您需要访问a/b/c,请将[]
更改为[&]
。
在c++11的情况下,如果需要访问a/b/c,将它们添加到some_helper
作为成员变量(或引用)并在some_helper
中初始化' s 构造函数,并从 some_function
.
传入它们
我使用的 c++14 功能是简洁语法模板化 lambda,它是生成琐碎 c++11 class 的语法糖。 c++14 lambda 还有一些我们不关心的(零成本)特性。
您需要在与不同变量定义相同的块中进行“其余计算”。有些情况下使用不同的类型;我希望该代码仅使用您显示的已定义代码。显然,代码可以分开。您还展示了两种情况,其中为同一类型调用了不同的构造函数;后续代码可以使用相同的变量,一旦它被创建。
但是你没有给出剩下的代码,我不知道:这四种情况有没有共同的处理方式?任何公共代码都可以进入子程序。
arma::mat some_function(bool a, bool b, unsigned long int c) {
if(a) {
if(b) {
arma::sp_mat d(c, c);
// Some other computations and a return statement
} else {
arma::SpMat<short> d(c, c);
// Some other computations and a return statement
}
} else {
if(b) {
arma::mat d(c, c, fill::zeros);
// Some other computations and a return statement
} else {
arma::Mat<short> d(c, c, fill::zeros);
// Some other computations and a return statement
}
}
// no return here; unreachable.
}
“其他计算”各自看到自己的变量。如果这四个分支之间有很多共性,把它放在一个它们都可以调用的公共子程序中。
我编写了一个有条件地初始化对象的 C++11 函数。考虑以下示例:
arma::mat some_function(bool a, bool b, unsigned long int c) {
if(a) {
if(b) {
arma::sp_mat d(c, c);
} else {
arma::SpMat<short> d(c, c);
}
} else {
if(b) {
arma::mat d(c, c, fill::zeros);
} else {
arma::Mat<short> d(c, c, fill::zeros);
}
}
// Some other computations and a return statement
}
如您所见,我想初始化一个对象 d
,其中 (Armadillo) 数据类型取决于布尔值 a
和 b
。不幸的是,它没有编译,编译器抱怨 d
没有在随后使用的范围内声明。
我发现了关于类似问题的各种讨论。条件初始化显然是在 C++17 中引入的。但是,我需要在此应用程序中使用 C++11。其他建议提及 type_traits
库和 lambda 函数。许多讨论都集中在有条件地指定对象的内容而不是它的数据类型上。由于我对 C++ 还很陌生,所以我不确定如何将这些选项中的任何一个应用于此嵌套条件结构。
您可能需要将通用代码放入一个 template
函数中,该函数可为所有 4 种不同类型实例化。然后,在所有 4 个分支中,调用此模板。编译器将生成 4 个不同的实例化。
template<class F>
arma::mat some_function(bool a, bool b, unsigned long int c, F f) {
if(a) {
if(b) {
arma::sp_mat d(c, c);
return f(d);
}
arma::SpMat<short> d(c, c);
return f(d);
}
if(b) {
arma::mat d(c, c, fill::zeros);
return f(d);
}
arma::Mat<short> d(c, c, fill::zeros);
return f(d);
}
arma::mat some_function(bool a, bool b, unsigned long int c){
return some_function(a, b, c,
[](auto&& d)->arma::mat{
// Some other computations and a return statement
}
);
}
我相信这可以解决您的问题,但需要 c++14。
这里的风格叫做“延续传递风格”;第一个模板创建变量 d
,然后将其传递给您传递给它的函数。然后它 returns 它需要什么函数 returns 当它反过来需要一个 d
.
底部 lambda 中的代码必须能够处理 d
模板函数中可能存在的任何类型,因为它不知道 bool 值是什么。
(如果 bool 值已知,还有其他方法,但通常答案是“如果你知道,并且只有一些有效,为什么 bool 值存在?)
c++14 特性编写起来非常简单,如果您告诉它使用 c++1y(它们的早期预编译器,大多数 c++11 编译器都支持它-C++14 的标准版本)。如果没有,您可以将其替换为:
[](auto&& d)->arma::mat{
// Some other computations and a return statement
}
与
struct some_helper {
template<class M>
arma::mat operator()(M&& m)const {
// Some other computations and a return statement
}
};
在some_function
之外,然后
arma::mat some_function(bool a, bool b, unsigned long int c){
return some_function(a, b, c,
some_helper{}
);
}
在c++14的情况下,如果您需要访问a/b/c,请将[]
更改为[&]
。
在c++11的情况下,如果需要访问a/b/c,将它们添加到some_helper
作为成员变量(或引用)并在some_helper
中初始化' s 构造函数,并从 some_function
.
我使用的 c++14 功能是简洁语法模板化 lambda,它是生成琐碎 c++11 class 的语法糖。 c++14 lambda 还有一些我们不关心的(零成本)特性。
您需要在与不同变量定义相同的块中进行“其余计算”。有些情况下使用不同的类型;我希望该代码仅使用您显示的已定义代码。显然,代码可以分开。您还展示了两种情况,其中为同一类型调用了不同的构造函数;后续代码可以使用相同的变量,一旦它被创建。
但是你没有给出剩下的代码,我不知道:这四种情况有没有共同的处理方式?任何公共代码都可以进入子程序。
arma::mat some_function(bool a, bool b, unsigned long int c) {
if(a) {
if(b) {
arma::sp_mat d(c, c);
// Some other computations and a return statement
} else {
arma::SpMat<short> d(c, c);
// Some other computations and a return statement
}
} else {
if(b) {
arma::mat d(c, c, fill::zeros);
// Some other computations and a return statement
} else {
arma::Mat<short> d(c, c, fill::zeros);
// Some other computations and a return statement
}
}
// no return here; unreachable.
}
“其他计算”各自看到自己的变量。如果这四个分支之间有很多共性,把它放在一个它们都可以调用的公共子程序中。