代码之家  ›  专栏  ›  技术社区  ›  LiraNuna

递归类型转换

  •  1
  • LiraNuna  · 技术社区  · 15 年前

    我有一个典型的“vector4”类,它有一个操作符float*来为gl*4fv和[]自动生成它。 还有“const”版本,用于优化编译器和const引用,这很好:

    typedef struct vec4
    {
        ...
    
        // ----------------------------------------------------------------- //
    
            // Cast operator, for []
        inline operator float* () { 
            return (float*)this;
        }
    
            // Const cast operator, for const []
        inline operator const float* () const { 
            return (const float*)this;
        }
    
        // ----------------------------------------------------------------- //
    
        ...
    
            // Vertex / Vector 
        struct {
            float x, y, z, w;
        };  
    
                // Color
        struct {
            float r, g, b, a;
        };
    } vec4;
    

    我的问题是,当我现在用支持 从矩阵中提取行,还具有“副作用”,即使用矩阵[][]运算符,这很好。

    typedef struct mat4
    {
        ...
    
        // ----------------------------------------------------------------- //
                // Cast operator, for []
        inline operator vec4* () { 
            return (vec4*)this;
        }
    
            // Const cast operator, for const []
        inline operator const vec4* () const { 
            return (const vec4*)this;
        }
        // ----------------------------------------------------------------- //
    
        private:
            float f[16];
    } mat4;
    

    我的问题是,为什么编译器没有检测到 Mat4浮动*?我怀疑Mat4->Vec4->Float*的传统是合理的,但似乎不是这样。 我想到,编译器可能会将其视为mat4->vec4*->float*,这是未定义的, 但是这个假设是无效的,因为定义了运算符

    inline operator const vec4 () const { 
        return (vec4)*this;
    }
    

    不起作用,调用glmultmatrixf(mat4(…));(例如)会生成与不使用运算符相同的错误消息。

    在mat4中定义操作符float*当然是不可能的,因为这将消除使用[][的能力(含糊不清的操作符)

    有什么解决办法吗?还是每次我想自动生成float*时都必须手动转换为vec4?自动转换是一个非常好的特性,它使用OpenGL巧妙地插入代码。

    2 回复  |  直到 15 年前
        1
  •  1
  •   young    15 年前

    …其中一个规则是不允许任何转换序列包含多个用户定义的转换(即对单个参数构造函数或隐式类型转换运算符的调用)。-更有效的C++,Scott Meyers

    您可能希望重载vec4和mat4的运算符[]。

    struct vec4
    {
        float& operator[](int index) { return f[index]; }
        const float& operator[](int index) const { return f[index]; }
    
        operator float*() { return f; }
        operator const float*() const { return f; }
    
        float f[4];
    };
    
    struct mat4 
    {
        vec4& operator[](int row) { return v[row]; }
        const vec4& operator[](int row) const { return v[row]; }
    
        operator float*() { return f; }
        operator const float*() const { return f; }
    
        union
        {
            vec4 v[4];
            float f[16];
        };
    };
    
    int main(void)
    {
        mat4 m;
        ::memset(&m, 0, sizeof(mat4));
        m[0][1] = 1;
        cout << m[0][1] << endl; // it prints 1.
    
        return 0;
    }
    
        2
  •  3
  •   Drew Dormann    15 年前

    C++可以执行自动转换,但是标准不会执行两个连续的自动转换。

    它被认为太有利于无意中的错误和模棱两可。

    三种可能对您有用的选项:

    当您需要 float* 从一个矩阵。

    FuncThatWantsFloatPointer( *static_cast<Vec4*>(MyMatrix) );
    

    实现直接对话到 浮动* 在矩阵类中。

    typedef struct mat4
    {
            ...
            operator const float* () const
            { 
                    return *static_cast<Vec4*>(*this);
            }
    
    } mat4;
    

    实施 operator[] 在矩阵和向量类中,如果您喜欢使用方括号表示法

    typedef struct mat4
    {
            ...
            const vec4& operator[] ( size_t index ) const
            { 
                    return static_cast<Vec4*>(*this)[index];
            }
    
    } mat4;