C++11 条件数据类型

问题描述

我写了一个 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,fill::zeros);
    }
  }
  // Some other computations and a return statement
}

如您所见,我想初始化一个对象 d,其中(Armadillo)数据类型取决于布尔值 ab。不幸的是,它没有编译,编译器抱怨 d 没有在它随后使用的作用域中声明。

我发现了关于类似问题的各种讨论。条件初始化显然是在 C++17 中引入的。但是,我需要在此应用程序中使用 C++11。其他建议提到了 type_traits 库和 lambda 函数。许多讨论集中在有条件地指定对象的内容而不是它的数据类型。由于我对 C++ 还很陌生,我不确定如何将这些选项中的任何一个应用于这个嵌套的条件结构。

解决方法

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,fill::zeros);
  return f(d);
}

arma::mat some_function(bool a,unsigned long int c){
  return some_function(a,b,[](auto&& d)->arma::mat{
      // Some other computations and a return statement
    }
  );
}

我相信这可以解决您的问题,但需要

这里的风格叫做“持续传递风格”;第一个模板创建变量 d,然后将其传递给您传递给它的函数。然后它返回它所采用的函数在它又采用 d 时返回的内容。

底部 lambda 中的代码必须能够处理 d 是它可能在模板函数中的任何类型,因为它不知道 bool 值是什么。

(如果知道 bool 值,还有其他方法,但通常答案是“如果您知道,并且只有一些有效,为什么会存在 bool?)

功能非常简单,大多数 编译器都支持它,如果您告诉它使用 (它们的 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,some_helper{}
  );
}

的情况下,如果您需要访问 a/b/c,请将 [] 更改为 [&]

的情况下,如果需要访问a/b/c,将它们作为成员变量(或引用)添加到some_helper中,并在some_helper的构造函数中初始化,并从 some_function 传入。

我使用的 功能是简洁的语法模板化 lambda,它是生成简单 类的语法糖。 lambda 还有一些我们不关心的(零成本)特性。

,

您可能需要将通用代码放在 template 函数中,该函数可以针对所有 4 种不同类型进行实例化。然后,在所有 4 个分支中,调用此模板。编译器将生成 4 个不同的实例。

,

您需要与不同变量定义在同一块中的“其余计算”。有使用不同类型的案例;我希望代码然后只使用您显示的定义的相同代码。显然,该代码可以分开。您还展示了为同一类型调用不同构造函数的两种情况;一旦创建了相同的变量,后续代码就可以使用相同的变量。

但是由于你没有展示其余的代码,我不知道:这四种情况之间有什么共同的处理吗?任何公共代码都可以进入子程序。

arma::mat some_function(bool a,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,fill::zeros);
        // Some other computations and a return statement
    } else {
      arma::Mat<short> d(c,fill::zeros);
        // Some other computations and a return statement
    }
  }
// no return here; unreachable.
}

“其他计算”每个都看到自己的变量。如果这四个分支之间有很多共同点,就放在一个他们都可以调用的公共子程序中。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...