C++ 具有CRTP和模板专门化的运算符的奇怪行为

C++ 具有CRTP和模板专门化的运算符的奇怪行为,c++,templates,operator-overloading,c++11,C++,Templates,Operator Overloading,C++11,我正在编写一个带有一些专门化的向量模板,以便根据大小为向量的前几项(如x、y、z、w)指定访问器。在这方面帮了大忙。我还添加了一种能够自然使用操作符的形式。下面是基类和带有附加函数的专门化(为了简洁起见,省略了大多数成员实现): 模板 类向量 { 公众: typedef ItemType value_type; VectorImpl(){elements.fill(0);} VectorImpl(std::initializer\u list init\u list); V运算符+(常数V和其他

我正在编写一个带有一些专门化的向量模板,以便根据大小为向量的前几项(如x、y、z、w)指定访问器。在这方面帮了大忙。我还添加了一种能够自然使用操作符的形式。下面是基类和带有附加函数的专门化(为了简洁起见,省略了大多数成员实现):

模板
类向量
{
公众:
typedef ItemType value_type;
VectorImpl(){elements.fill(0);}
VectorImpl(std::initializer\u list init\u list);
V运算符+(常数V和其他)
{
V结果;
对于(int i=0;i元素[0];}
ItemType y()常量{返回此->元素[1];}
ItemType z()常量{返回此->元素[2];}
};

我想添加
qDebug()给输出函数一个const引用,或者右值(比如添加后的临时值)不会绑定到它(实际上,实际常数也不会绑定):


为输出函数指定一个常量引用,否则右值(例如加法后的临时值)将不会绑定到输出函数(实际上,实际常数也不会绑定到输出函数):


我觉得这个问题(不做参考常数)经常会出现。@TamásSzelei:发生在最好的情况下…:-)我觉得这个问题(不做参考常数)经常会出现。@TamásSzelei:发生在最好的情况下…:-)
template<int Dim, typename V, typename ItemType = float>
class VectorImpl
{
public:
    typedef ItemType value_type;    
    VectorImpl() { elements.fill(0); }    
    VectorImpl(std::initializer_list<ItemType> init_list);

        V operator+(const V& other)
    {
        V result;
        for (int i = 0; i < Dim; ++i) 
            result.elements[i] = elements[i] + other.elements[i];

        return result;
    }

    QString toString();    
        // ... other members ...

protected:
    VectorImpl(const VectorImpl& other) = default;

protected:
    std::array<ItemType, Dim> elements;
};

template<int Dim, typename ItemType = float>
class Vector : public VectorImpl<Dim, Vector<Dim, ItemType>, ItemType>
{
    typedef VectorImpl<Dim, Vector<Dim, ItemType>, ItemType> ParentType;
public:
    Vector() : ParentType() {}
    Vector(const ParentType& other) : ParentType(other) {}
    Vector(std::initializer_list<ItemType> init_list) : ParentType(init_list) {}
};

template<typename ItemType>
class Vector<3, ItemType> : public VectorImpl<3, Vector<3, ItemType>, ItemType>
{
    typedef VectorImpl<3, Vector<3, ItemType>, ItemType> ParentType;
public:
    Vector() : ParentType() {}
    Vector(const ParentType& other) : ParentType(other) {}
    Vector(std::initializer_list<ItemType> init_list) : ParentType(init_list) {}
    ItemType x() const { return this->elements[0]; }
    ItemType y() const { return this->elements[1]; }
    ItemType z() const { return this->elements[2]; }
};
template<int Dim, typename ItemType>
QDebug operator<<(QDebug dbg, Vector<Dim, ItemType>& v)
{
    dbg.nospace() << v.toString();
    return dbg.space();
}
Vector<3> v1 = { 3,4,5 };
qDebug() << v1;
Vector<3> v1 = { 3,4,5 };
Vector<3> v2 = { 1,-1,1 };
qDebug() << v1;
auto v3 = v1 + v2;
qDebug() << v3;
Vector<3> v1 = { 3,4,5 };
Vector<3> v2 = { 1,-1,1 };
qDebug() << (v1 + v2);
QDebug operator<<(QDebug dbg, Vector<Dim, ItemType> const & v)
//                                                  ^^^^^
QString toString() const;
//                 ^^^^^