使用枚举编译时多态性

Compile time polymorphism with enums

本文关键字:多态性 编译 枚举      更新时间:2023-10-16

所以,这些问题与枚举继承有关,我在这里看到了很多主题,其中描述了如何编写支持继承的枚举的方法,但我认为这不是我的情况。

我找到了一些我想做的东西。所以这个想法是我有一个类,让它成为 OpenGL 纹理类(实际上是),并且有枚举表示纹理中一个属性的所有可能值。

class Texture
{
    public:
        enum Filter
        {
            LINEAR   = 1,
            BILINEAR = 2,
            ANISOTROPIC = 3
        };
    public:
        Texture(Filter _filter)
            : filter(_filter) 
        { }
    private:
        Filter filter;
};

以及继承它的类。派生类中的枚举必须重新定义,但我可以在基类的构造函数中进一步使用:

class Texture2d : public Texture
{
    public:
        enum Filter
        {
            LINEAR   = 1,
            BILINEAR = 2
        };
    public:
        Texture2d(Filter _filter)
            : Texture(_filter)
        { }
};

但是,当然,这是行不通的,因为新创建的FilterTexture2d::Filter,但不是Texture::Filter .

我尝试使用这样的enum class

class Texture
{
    public:
        enum class Filter;
    public:
        Texture(Filter _filter)
            : filter(_filter)
        { }
    private:
        Filter filter;
};
class Texture2d : public Texture
{
    public:
        enum Filter
        {
            LINEAR = 1,
            BILINEAR = 2
        };
    public:
        Texture2d(Filter _filter)
            : Texture(_filter)
        { }
};

但这确实是一个愚蠢的想法。我想,如果我只想扩展枚举,我会写一些类包装器,但我也需要缩小枚举。所以问题是,如何让这个东西在编译时工作?这是主要问题 - 在编译时使其工作。还有一个问题:实际上尝试做这些事情是可以的,或者我必须检查我的应用程序的架构?

(所有答案将不胜感激)

我没有看到你的代码有问题。
你只需要在Texture2d的构造函数中添加一个强制转换。

Texture2d(Filter _filter) // no Texture::Filter
    : Texture(static_cast<Texture::Filter>(_filter))
{ }
Texture t1(Texture::LINEAR);           // WORKS
Texture t2(Texture::BILINEAR);         // WORKS
Texture t3(Texture::ANISOTROPIC);      // WORKS
Texture2d t4(Texture2d::LINEAR);       // WORKS
Texture2d t5(Texture2d::BILINEAR);     // WORKS
Texture2d t6(Texture2d::ANISOTROPIC);  // ERROR

那是因为Texture2d::ANISOTROPIC被解释为Texture::ANISOTROPIC因为不存在Texture2d::Filter::ANISOTROPIC

由于Texture2d构造函数都不接受Texture::Filter因此会导致错误。

枚举没有继承 - 所以扩展/减少的想法是不可能的。相反,您可以做的是在它们之间提供Texture2d转换方法:

class Texture2d : public Texture {
public:
    enum class Filter {
        LINEAR, BILINEAR
    };
    Texture2d (Filter f)
    : Texture(convert(f))
    { }
private:
    Texture::Filter convert(Filter f) {
        switch(f) {
        case Filter::LINEAR: return Texture::Filter::LINEAR;
        // etc.
        default: 
            // ? Maybe throw? 
     }
};

这让你在每个子类中指定有效枚举的列表。但是,如果您通常希望允许相同的内容,则可能会重复。