C++ 如何在c+中标记要转换到哪个类+;?

C++ 如何在c+中标记要转换到哪个类+;?,c++,types,casting,template-meta-programming,C++,Types,Casting,Template Meta Programming,我正在寻找一些方法来标记我想投给的班级。我是这个网站的新手,所以请随时改进标签或其他东西 例如,如果我有: template<class C> class Rotateable { virtual void C Rotate() = 0; }; class Circle : public Rotateable<Circle> { Circle Rotate() { /*impl here*/ } }; class Square : public Rot

我正在寻找一些方法来标记我想投给的班级。我是这个网站的新手,所以请随时改进标签或其他东西

例如,如果我有:

template<class C>
class Rotateable
{
    virtual void C Rotate() = 0;
};

class Circle : public Rotateable<Circle>
{
    Circle Rotate() { /*impl here*/ }
};

class Square : public Rotateable<Square>
{
    Square Rotate() { /*impl here*/ }
};
模板
类可旋转
{
虚空C Rotate()=0;
};
班级圈子:公众可轮换
{
圆旋转(){/*impl here*/}
};
广场类:公共旋转
{
方形旋转(){/*impl here*/}
};

如果我有一个
rotatable
s的列表或数组,我如何在某个地方(在
rotatable
?)存储要尝试和强制转换到哪个类的信息,以一种我可以在运行时访问的方式?

您不能有返回类型更改的虚拟机。但是您可以在多态类上具有类型标识符,这些标识符在调用函数之前告诉您要转换到哪个类。让我们来看看这样的基本想法。(这是c++14代码。如果您不使用c++14功能,请随意删除任何不适合您的部分。)

#包括
#包括
#包括
大小\u t生成\u id()
{
静态大小\u t id=0;
返回id++;
}
模板
大小\u t类型\u id()
{
静态大小\u t id=生成\u id();
返回id;
}
类可旋转
{
公众:
模板
布尔是
{
返回类型_id()==type();
}
虚拟大小\u t type()=0;
};
模板
类可旋转:公共BaseRotatable
{
公众:
size\u t type()重写
{
返回类型_id();
}
};
类圈:公共可旋转
{
公众:
圆旋转()
{
return*this;//让它做一些更有趣的事情。
}
};
广场类:公共旋转
{
公众:
方形旋转()
{
return*this;//让它做一些更有趣的事情。
}
};
模板
标准::唯一的ptr工厂(Args…Args)
{
T*ptr=新的T(参数…);
返回std::unique_ptr{dynamic_cast(ptr)};
}
int main(){
//构建一个可旋转向量。
std::向量可旋转;
可旋转。向后放置(factory());
可旋转。向后放置(factory());
用于(自动和可旋转:可旋转)
{
//您也可以在此处使用开关。
如果(可旋转->是())
{
圆和圆=*动态_转换(rotatable.get());
自动新建_圆=圆。旋转();

std::难道你不能真正拥有一个可旋转的
实例列表或数组吗?因为它是一个模板,你可以拥有一个可旋转的
集合和另一个可旋转的
集合,但你不能在一个集合中同时拥有这两个实例,除非你使用例如
std::any
。是的,我会看看是否可以将其更改为按照我的意思来做。是的,你是对的。它不允许在列表中使用模板。它看起来确实不可能。我会更好地继承一些EnUM标记,或者其他丑陋的东西。或者等待C++的哪个版本我们得到STD::什么?这似乎是一个好的老多态性的好地方,而不是模板。我还需要跨类工作的运算符。我不希望虚拟机更改返回类型,我希望强制执行继承以实现返回其自己类的对象的某些函数。您不能。强制执行的唯一方法是在基类中有一个虚拟机。如果基类有一个虚拟机,则它有一个特定的返回类型e、 它不能在不同的派生类中返回不同的内容返回自己类型的对象的函数,每个函数都必须是不同的函数。这意味着,它们完全独立于基类。使用奇怪的循环模板模式很容易做到这一点。当我想将从这些对象派生的对象填充到公共列表中时,我的斗争就开始了。要将对象放入公共列表中,它们应该不管是哪种方法,都需要一个普通的基类,或者是原始指针。不管怎样,你需要确定哪个对象是你把它们从列表中拿走的。这就是我在例子中用IDS做的。当然还有其他方法。但是你不能有一个混合类型的容器,而不需要自己运行一些时间。C++不维护T。在运行时键入信息。是的,键入ID可能是我可以这样做的一种方法。谢谢。
#include <iostream>
#include <memory>
#include <vector>

size_t generate_id()
{
    static size_t id = 0;
    return id++;
}

template <typename T>
size_t type_id()
{
    static size_t id = generate_id();
    return id;
}

class BaseRotatable
{
public:
    template <typename T>
    bool is()
    {
        return type_id<T>() == type();
    }

    virtual size_t type() = 0;
};

template <typename T>
class Rotatable : public BaseRotatable
{
public:
    size_t type() override
    {
        return type_id<T>();
    }
};

class Circle : public Rotatable<Circle>
{
public:
    Circle Rotate()
    {
        return *this; // Make this do something fancier.
    }
};

class Square : public Rotatable<Square>
{
public:
    Square Rotate()
    {
        return *this; // Make this do something fancier.
    }
};

template <typename T, typename... Args>
std::unique_ptr<BaseRotatable> factory(Args... args)
{
    T* ptr = new T(args...);
    return std::unique_ptr<BaseRotatable>{dynamic_cast<BaseRotatable*>(ptr)};
}

int main() {
    // Build a vector of rotatables.
    std::vector<std::unique_ptr<BaseRotatable>> rotatables;
    rotatables.emplace_back(factory<Circle>());
    rotatables.emplace_back(factory<Square>());

    for (auto& rotatable : rotatables)
    {
        // You can also use a switch here.
        if (rotatable->is<Circle>())
        {
            Circle& circle = *dynamic_cast<Circle*>(rotatable.get());
            auto new_circle = circle.Rotate();
            std::cout << "Type id: " << new_circle.type() << std::endl;
        }
        else if (rotatable->is<Square>())
        {
            Square& square = *dynamic_cast<Square*>(rotatable.get());
            auto new_square = square.Rotate();
            std::cout << "Type id: " << new_square.type() << std::endl;
        }
    }
    return 0;
}