In my code, I have one abstract class and ~8 child classes. I want to ask, is it possible in C to cast typename
and return the calling class? I need something like separate A<int>
as A
and int
. I need something like this:
template <typename T>
class Base
{
T data;
virtual void setData(T p_data) = 0;
virtual ~Base();
template<class TC<typename TV>>
operator TC<TV>() const
{
TV tmp = (TV) data;
return TC<TV>(tmp);
}
};
template <typename T>
class A : public Base<T>
{
A(T data)
{
std::cout << data << std::endl;
}
void setData(T p_data) override
{
data = p_data;
}
};
I used to use D. In D, the next code solves this problem (I have included the D code below for a better understanding of what I want):
auto opCast(K, this R)() const
{
static if (is(R ClassType : Root!T, alias Root))
K tmp = cast(K) data;
return new Root!K(tmp);
else
throw new Exception("ClassType isn't equal (T)");
}
Is there a solution for C ?
CodePudding user response:
If I'm reading your D code correctly, you are basically:
- taking the
ClassType
of thethis
object that is being converted, - pattern-matching it to make sure it is a template with 1 argument, and then extracting the type of that template,
- casting the
this
object'sdata
member to a specified input type, - returning a new object of the template with the specified type as its argument.
There is nothing like ClassType
in C , so it is not possible for a base class to obtain the class type of a derived object, unless you use CRTP to pass the derived type as a template parameter to the base class.
However, the operator
you have is close to accepting any kind of template type for conversion, your syntax is just a little wrong. Try something more like this:
template <typename T>
class Base
{
public:
T data;
...
template<template<typename> typename TC, typename TV>
operator TC<TV>() const
{
TV tmp = (TV) data;
return TC<TV>(tmp);
}
};
Then something like this would work:
A<int> d(7);
A<float> e = d;
std::cout << e.data << std::endl;
The catch is that this operator
will convert to any template that takes an argument that data
can be converted to. If you want to restrict the operator
to only the same template that is being converted, you will need something more like this:
template <typename T, template<typename> typename Derived>
class Base
{
public:
T data;
...
template<typename TV>
operator Derived<TV>() const
{
return Derived<TV>(data);
}
};
template <typename T>
class A : public Base<T, A>
{
typedef Base<T, A> my_base;
public:
A(T p_data)
{
setData(p_data);
std::cout << my_base::data << std::endl;
}
void setData(T p_data) override
{
my_base::data = p_data;
}
};