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) 数据类型取决于布尔值 ab。不幸的是,它没有编译,编译器抱怨 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
    }
  );
}

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

这里的风格叫做“延续传递风格”;第一个模板创建变量 d,然后将其传递给您传递给它的函数。然后它 returns 它需要什么函数 returns 当它反过来需要一个 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, bool b, unsigned long int c){
  return some_function(a, b, c,
    some_helper{}
  );
}

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

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

传入它们

我使用的 功能是简洁语法模板化 lambda,它是生成琐碎 class 的语法糖。 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.
}

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