Question

How do I get type conversion to work when cascading the type conversions?

The following code should be simple, but converison from TypeB to int requires the compiler to deduce two type conversions automatically. But it does not.

I can not simply implement operator int() const { return val; } on the TypeB class because this is supposed to be a template class And I can not know which type to convert to.

class TypeA {
public:
   TypeA( int a ) : val( a ) {}
   operator int () const { return val; }
private:
   int val;
};

class TypeB {
public:
   TypeB( TypeA a ) : val( a ) {}
   operator TypeA () const { return val; }
   // operator int() const { return val; }  // Explicit conversion to int which I can not know.
private:
   TypeA val;
};

void main() {
   TypeA a = 9;
   TypeB b = a;
   int int_a = a;
   TypeA a2 = b;
   int int_b = b;    // Compilation error: 
                     // No suitable conversion function from 'TypeB' to 'int' exists
}

Regards

Was it helpful?

Solution 2

So you want TypeB<T> to use the user defined conversions of T?

Create a template operator U that uses SFINAE to examine the conversion operators of T and accept when U is a type T has an operator U for.

An insufficient, yet easy, way is std::is_convertible -- address of T::operator U is probably better.

This will require C++11 features to do reasonably, because you'll want to use enable_if in a default template parameter.

This is a sketchy implementation: I don't cover the target type having a constructor that takes the source type.

#include <utility>
#include <type_traits>
#include <iostream>

struct A {
  operator int() { return 7; }
};

template<typename T>
struct unevaluated: std::true_type {};

template<typename T, typename U, typename=void>
struct has_user_defined_conversion:std::false_type {};

template<typename T, typename U>
struct has_user_defined_conversion<T, U,
  typename std::enable_if< unevaluated<
    decltype(
      &T::operator U
    )
  >::value >::type
>: std::true_type {};

template<typename T>
struct fake {
  T t;
  template<typename U,
    typename=typename std::enable_if<has_user_defined_conversion<T,U>::value>::type
  >
  operator U() { return t; }
};

int main() {
  int x = fake<A>();
  std::cout << x << "\n";
}

OTHER TIPS

In any implicit conversion sequence you are allowed at most one implicit user-defined conversion.

You can say int int_b = static_cast<TypeA>(b);, though, to bring the number of UDCs down to one.

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