从虚拟 class 转换派生模板 class

Casting derived template class from virtual class

在我的代码中,我有一个抽象 class 和 ~8 个子 classes。我想问一下,在C++中是否可以将typename和return转换为调用class?我需要像 A<int>Aint 这样的东西。我需要这样的东西:

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;
    }
};

我以前用D。在D中,下一个代码解决了这个问题(为了更好地理解我想要什么,我在下面包含了D代码):

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)");
    }

是否有针对 C++ 的解决方案?

如果我正确阅读了你的 D 代码,那么你基本上是:

  • 取正在转换的this对象的ClassType
  • 对其进行模式匹配以确保它是具有 1 个参数的模板,然后提取该模板的类型,
  • this 对象的 data 成员转换为指定的输入类型,
  • 以指定类型作为参数返回模板的新对象。

C++中没有ClassType,所以基类class不可能获得派生对象的class类型,除非你使用CRTP 将派生类型作为模板参数传递给基础 class.

但是,您的operator接近于接受任何类型的模板类型进行转换,您的语法有点错误。试试这样的东西:

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);
    }
};

然后像这样的东西会起作用:

A<int> d(7);
A<float> e = d;
std::cout << e.data << std::endl;

Online Demo

要注意的是,此 operator 将转换为 任何 模板,该模板采用 data 可以转换为的参数。如果您想将 operator 限制为仅转换为同一模板,您将需要更多类似的内容:

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;
    }
};

Online Demo