Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

type conversion for templates

I have a wrapper class template and want to have implicit conversion to the wrapped type in order to use existing library functions:

#include <complex>

double f(double x) { return 1.; }

template <typename T>
std::complex<T> f(std::complex<T> x) { return std::complex<T>(); }

template <typename T>
class A {
  T _x;
public:
  A(const T& x) : _x(x) {}
  operator T() { return _x; }
};

int main() {
  A<double> da(1.);
  A<std::complex<double>> ca({1.,1.});
  f(da); // OK                                                                                                                  
  f(ca); // error                                                                                                               
  return 1;
}

The f(std::complex<T>) is not used for f(ca) because implicit conversion is not considered during template argument deduction (see the generated error msg. here).

In the real code f(...) is replaced by library functions e.g. from the <complex> header, so it can't be modified.

If I inherit A from T (as suggested by the error message) then f(ca) compiles. But then A is not defined for built-in types (you can't inherit from them). Also, that would give all the functionality of complex<double> to A<complex<double>> which I want to avoid.

Is there any workaround for this?

like image 555
M Zetenyi Avatar asked Apr 20 '15 23:04

M Zetenyi


People also ask

What is a template type?

There are three kinds of templates: function templates, class templates and, since C++14, variable templates. Since C++11, templates may be either variadic or non-variadic; in earlier versions of C++ they are always non-variadic.

What are the types of type conversion?

There are two types of conversion: implicit and explicit. The term for implicit type conversion is coercion. Explicit type conversion in some specific way is known as casting. Explicit type conversion can also be achieved with separately defined conversion routines such as an overloaded object constructor.

What is type conversion with example?

In computer science, type conversion, type casting, type coercion, and type juggling are different ways of changing an expression from one data type to another. An example would be the conversion of an integer value into a floating point value or its textual representation as a string, and vice versa.

What is a standard type conversion?

The C++ language defines conversions between its fundamental types. It also defines conversions for pointer, reference, and pointer-to-member derived types. These conversions are called standard conversions.


1 Answers

To resolve the "doesn't work for built-in types" problem, you can use a template specialization. The std::complex<> version uses inheritance.

template <typename T>
class A {
  T _x;
public:
  A(const T& x) : _x(x) {}
  operator const T &() const { return _x; }
  operator T &() { return _x; }
};

template <typename D>
class A<std::complex<D>> : public std::complex<D> {
  typedef std::complex<D> T;
public:
  A(const T& x) : T(x) {}
};

If inheritance is not acceptable, the only approach I am aware of is to define functions that take A<> as an argument. However, you can simplify the task by defining the functions within A<> itself, and thus leveraging a simplified syntax for the template argument, and argument dependent lookup for function call invocation.

template <typename T>
class A {
  T _x;
  friend A f(A x) { return f(x._x); }
public:
  A(const T& x) : _x(x) {}
  operator const T &() const { return _x; }
  operator T &() { return _x; }
};
like image 78
jxh Avatar answered Oct 25 '22 19:10

jxh