Question

I have a piece of code to use the RTTI as case selector

#include <iostream>
#include <vector>
#include <typeinfo>
#include <complex>
#include <algorithm>

using namespace std;

typedef complex<int> data;
typedef std::vector< data > List;

template <typename T> void zeros(T &v)
{
  if (typeid(typename T::value_type)==typeid(complex<int>))
    std::fill(v.begin(), v.end(), complex<int>(0, 0));
  else std::fill(v.begin(), v.end(), static_cast<typename T::value_type>(0));
}

int main(int argc, char *argv[])
{
  List A;

  zeros(A);
  return 0;
}

In above code, I use typename T::value_type to determine the data type of the list, if there is complex then I will fill the list with complex zero. Otherwise, make it zero of the corresponding type. In above code, if I set data to be int, it does compile and run without any problem. But if I set it another other type, it fail to compile. I wonder if there is any way to make above code work for different type of data (for float, double, long, int, complex, complex and complex).

p.s. the reason I want to fill the vector in two cases because I am going to create my own complex for some reason and I have to tell the code how to create the complex zero or real zero. But for testing, I can't even make it work with built-in datatype

Was it helpful?

Solution

It seems that you want both a default initialized complex (0, 0), and a zero initialized int. You can achieve this using value initialization:

template <typename T> void zeros(T &v)
{
    std::fill(v.begin(), v.end(), typename T::value_type{});
}

If you really want to perform some branching depending on what is T::value_type, then it would be better to use some type trait, like the following one:

template<typename T>
struct default_value {
    static const T value;
};

template<>
struct default_value<std::complex<int>> { // assuming you'll use other complex type
    static const std::complex<int> value;
};

template<typename T>
const T default_value<T>::value = T{};
const std::complex<int> default_value<std::complex<int>>::value = std::complex<int>(0, 0);

// now use it
template <typename T> void zeros(T &v)
{
    std::fill(v.begin(), v.end(), default_value<typename T::value_type>::value);
}

But again, default construction and value initialization for built in types should be enough.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top