Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove redundant template types

Tags:

c++

templates

I am currently struggling with templates: I have a templated class A, which performs basic math (for floats, doubles, complex numbers) and looks like this

template <typename T>
class A
{  
public:
    void foo(std::vector<std::complex<T>>& result);
};

Now I can use the class like A<double>, A<float>, but I would also like to use it like A<std::complex<float>> and A<std::complex<double>>. When using the latter, I would like the definition of foo to look like

void foo(std::vector<std::complex<float>>& result);

and not like

void foo(std::vector<std::complex<std::complex<float>>>& result);

Is there any way to create a specific template for the std::complex<T> cases, in which I can access the "inner" type? Or this is not possible/bad practice? What is the most elegant way to solve this issue?

like image 624
zimmerrol Avatar asked Oct 28 '17 12:10

zimmerrol


2 Answers

Another way can pass through the creation of a type traits to detect the (extract, when needed) the float type

template <typename T>
struct getFloatType
 { using type = T; };

template <typename T>
struct getFloatType<std::complex<T>>
 { using type = T; };

and use it in A (see fT)

template <typename T>
class A
 {  
   public:
      using fT = typename getFloatType<T>::type;

      void foo(std::vector<std::complex<fT>>& result)
       { }
 };
like image 95
max66 Avatar answered Sep 18 '22 13:09

max66


You can make a partial specialization for any instantiation of std::complex, e.g.

template <typename T>
class A<std::complex<T>>
{  
public:
    void foo(std::vector<std::complex<T>>& result);
};

Then for A<std::complex<double>>, the signature of foo would be void foo(std::vector<std::complex<double>>& result);.

To handle those duplicated codes, you can make a base class and move the common members into it, and make the primary template and partial specialization both derive from it. e.g.

class Base {
public:
    void bar(...);
};

then

template <typename T>
class A : public Base {
    ...
};

template <typename T>
class A<std::complex<T>> : public Base {
    ...
};
like image 37
songyuanyao Avatar answered Sep 22 '22 13:09

songyuanyao