Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change member-typedef depending on template parameter?

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.

like image 229
goocreations Avatar asked Jun 05 '14 06:06

goocreations


People also ask

What is the difference between member and function template?

The term member template refers to both member function templates and nested class templates. Member function templates are template functions that are members of a class or class template. Member functions can be function templates in several contexts. All functions of class templates are generic but are not referred to as member templates ...

What is a member template in Java?

The term member template refers to both member function templates and nested class templates. Member function templates are template functions that are members of a class or class template. Member functions can be function templates in several contexts.

Can a local class have a member template?

Local classes are not allowed to have member templates. Member template functions cannot be virtual functions and cannot override virtual functions from a base class when they are declared with the same name as a base class virtual function. The following example shows a templated user-defined conversion:

What is a type parameter in a template?

Type template parameter. In the body of the template declaration, the name of a type parameter is a typedef-name which aliases the type supplied when the template is instantiated. There is no difference between the keywords class and typename in a type template parameter declaration.


2 Answers

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>
}
like image 197
Filip Roséen - refp Avatar answered Sep 30 '22 05:09

Filip Roséen - refp


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.

like image 44
user657267 Avatar answered Sep 30 '22 07:09

user657267