Change member-typedef depending on template parameter?

偶尔善良 提交于 2019-12-06 02:08:07

问题


I have this problem here that I can’t figure out how to solve. I want a template class that takes an integer as template parameter and sets the template parameters for another class accordingly:

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();

};

And then calling it like this:

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

How can I do something like this? At the moment with the code above, the compiler complaints that it doesn't know "Matrix", so I'm not sure if you can use the preprocessor on template parameters.


回答1:


INTRODUCTION

Since you'd like S<N>::Matrix to yield a different type depending on the N passed, you will need to use some sort of meta template programming. The question is currently tagged with preprocessor, and the snippet explicitly tries to use it; but that is of little to no use in this case.

When the code is being preprocessed N is nothing more than a name, it hasn't got a value; yet.


Solution

The description mentiones if, if ... else, and else; and we are dealing with types.. looking through <type_traits> it seems like std::conditional would be a perfect match!

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

Note: Depending on whether the expression found in condition yields true, or false, ::type will be a typedef for either type-if-true, or type-if-false.


Let's write a sample implementation:

#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>
}



回答2:


You can use std::conditional for this, although whether you should be doing this in the first place is another kettle of fish:

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

You'll need to use std::conditional and ::type instead of conditional_t if your compiler doesn't support it.




回答3:


No, you can't use the preprocessor on template parameters.

The preprocessor is just doing very simple string processing on your input source. It has no glue about types and I think it is run as the very first step while first processing the file and collecting all the includes. Templates are something the compiler itself takes care of. At this point the preprocessor has finished already.

A similar question has been asked here: Use a template parameter in a preprocessor directive?



来源:https://stackoverflow.com/questions/24053582/change-member-typedef-depending-on-template-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!