【问题标题】:Change member-typedef depending on template parameter?根据模板参数更改成员类型定义?
【发布时间】:2014-07-26 01:21:16
【问题描述】:

我这里有这个问题,我不知道如何解决。我想要一个模板类,它接受一个整数作为模板参数并相应地为另一个类设置模板参数:

template <int T>
class Solver
{

  public:

    #if T <= 24
      typedef MyMatrix<float> Matrix;
    #else if T <= 53
      typedef MyMatrix<double> Matrix;
    #else
      typedef MyMatrix<mpreal> Matrix;
    #endif

    Matrix create();

};

然后这样称呼它:

Solver<53>::Matrix m = Solver<53>::create();

我该如何做这样的事情?目前使用上面的代码,编译器抱怨它不知道“矩阵”,所以我不确定你是否可以在模板参数上使用预处理器。

【问题讨论】:

  • MyMatrix 定义在哪里?
  • 在编译之前会评估预处理器条件,因此您现在尝试的将不起作用(就预处理器而言,未定义 T)。
  • MyMatrix 是一个在别处定义的简单矩阵类,并接受一个类型作为参数。

标签: c++ templates c-preprocessor


【解决方案1】:

简介

由于您希望S&lt;N&gt;::Matrix 根据传递的N 产生不同的类型,因此您需要使用某种元模板编程。该问题当前使用 preprocessor 标记,并且 sn-p 明确尝试使用它;但这在这种情况下几乎没有用。

当代码被预处理时N只是一个名字,它没有一个值;还没有。


解决方案

描述中提到了ifif ... elseelse;我们正在处理类型..通过&lt;type_traits&gt; 看起来std::conditional 将是一个完美的匹配!

std::conditional<condition, type-if-true, type-if-false>::type;

注意:取决于在condition 中找到的表达式是产生true 还是false::type 将是typedef 表示 type-if-truetype-if-false


让我们编写一个示例实现:

#include <type_traits>

template <int N>
class Solver
{
  public:
    typedef typename std::conditional<
      /*    */ (N <= 24),
      /* y? */ MyMatrix<float>,
      /* n? */ typename std::conditional<(N <= 53), MyMatrix<double>, MyMatrix<mpreal>>::type
    >::type matrix_type;

  ...
};

int main () {
  Solver<53>::matrix_type a; // Matrix<double>
  Solver<10>::matrix_type b; // Matrix<float>
  Solver<99>::matrix_type c; // Matrix<mpreal>
}

【讨论】:

  • 不错的解决方案。今天了解了std::conditional
  • 正是我想要的。谢谢 Filip,你让我的工作轻松多了。
  • @RSahu:哇,我也是。就是这么简单! :) 只是false 案例的模板规范。很酷:template &lt;bool _Bp, class _If, class _Then&gt; struct conditional {typedef _If type;};template &lt;class _If, class _Then&gt; struct conditional&lt;false, _If, _Then&gt; {typedef _Then type;};
  • std::conditional 需要 C++11。你有 C++03 及更高版本的东西吗?虽然 GCC 4.8 和 4.9 还活着,但我们需要支持 C++03。
【解决方案2】:

您可以为此使用std::conditional,尽管您是否应该首先这样做是另一回事:

template<int T>
class Solver
{
  std::conditional_t<
    T <= 24,
    MyMatrix<float>,
    std::conditional_t<
      T <= 53,
      MyMatrix<double>,
      MyMatrix<mpreal>
    >
  > Matrix;
};

如果您的编译器不支持,您需要使用std::conditional::type 而不是conditional_t

【讨论】:

    【解决方案3】:

    不,您不能对模板参数使用预处理器。

    预处理器只是对您的输入源进行非常简单的字符串处理。它没有关于类型的胶水,我认为它是在首先处理文件并收集所有包含时作为第一步运行的。模板是编译器自己负责的。此时预处理器已经完成。

    这里有人问过一个类似的问题: Use a template parameter in a preprocessor directive?

    【讨论】:

    • 谢谢。还有其他方法吗?在您发布的链接中,最后一个答案提供了一种解决方案,但是您必须为参数的每个值添加一个子类,我想为整个范围指定一个类。
    • 这样的规范正是std::conditional 的工作原理,他们只是为你打包,所以你不需要自己做! :)
    猜你喜欢
    • 2017-09-11
    • 1970-01-01
    • 2017-03-14
    • 1970-01-01
    • 2020-03-28
    • 1970-01-01
    • 2015-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多