【问题标题】:Conversion operator from one templated class to another, related template class从一个模板类到另一个相关模板类的转换运算符
【发布时间】:2017-05-04 18:23:20
【问题描述】:

进行了搜索,但找不到与我的查询匹配的内容,它有点具体,所以就这样吧。

我有一些模板类(Vector2、Vector3 和 Vector4)。 试图定义一个从 Vector2 到 3 和 4 的转换运算符, 和 Vector3 到 2 和 4 等。

template <typename T>
class Vector4 {
    // ...
    operator Vector2<T>() const { return { x, y }; }
    operator Vector3<T>() const { return { x, y, z }; }
    // ...
    T x, y, z, w;
    // ...
}


template <typename T>
class Vector3 {
    // ...
    operator Vector2<T>() const { return { x, y }; }
    operator Vector4<T>() const { return { x, y, z, 0 }; }
    // ...
    T x, y, z;
    // ...
}


template <typename T>
class Vector2 {
    // ...
    operator Vector3<T>() const { return { x, y, 0 }; }
    operator Vector4<T>() const { return { x, y, 0, 0 }; }
    // ...
    T x, y;
    // ...
}

使用 Visual Studio 2017 给了我这个:

错误 C2833:'operator Vector2' 不是可识别的运算符或类型

感谢所有帮助。

谢谢。

编辑:我的实际来源在类定义后确实有分号。忘了把它们放在我发布的简短版本中。 另外,是的,有很多错误,但根据我的经验,这通常是第一个重要的 尝试向前声明:

template <class T> class Vector 3;
template <class T> class Vector 4;

template <typename T> 
class Vector2 {
// ...
}

编辑:现在我收到错误 C2988:无法识别的模板声明/定义。可能值得一提的是,这 3 个模板类位于不同的文件中。我最初尝试在一个类中包含一个标题以使类型转换运算符正常工作,这就是导致原始错误的原因。

哦,是的。我一定会把这些说清楚。这总是很好的建议。不过现在是当地时间 0430... :)

编辑:没关系,我是个垃圾。我不知道我是如何在 Vector 和暗淡数量“Vector 2”!=“Vector2”之间插入一个空格的。前向声明它是。不敢相信我错过了这么简单的事情。 孩子们:当你被束缚时不要编码,这很好。

【问题讨论】:

  • 您可能需要考虑声明这些运算符explicit
  • 它应该提供更多的错误信息。我可以看到你应该在哪里得到至少 10... 用分号关闭类定义。编译器在声明之前无法识别类型。

标签: c++ templates conversion-operator


【解决方案1】:

当您声明 Vector4&lt;T&gt;::operator Vector2&lt;T&gt;() const; 时,您正在使用类 Vector2&lt;T&gt; 在声明之前。 Vector4&lt;T&gt;::operator Vector3&lt;T&gt;() const; 也会发生同样的事情。先转发声明你的类。

// Forward declarations
template<class T> class Vector2;
template<class T> class Vector3;

template <typename T>
class Vector4 {
    // ...
    operator Vector2<T>() const { return{ x, y }; }
    operator Vector3<T>() const { return{ x, y, z }; }
    // ...
    T x, y, z, w;
    // ...
};


template <typename T>
class Vector3 {
    // ...
    operator Vector2<T>() const { return{ x, y }; }
    operator Vector4<T>() const { return{ x, y, z, 0 }; }
    // ...
    T x, y, z;
    // ...
};


template <typename T>
class Vector2 {
    // ...
    operator Vector3<T>() const { return{ x, y, 0 }; }
    operator Vector4<T>() const { return{ x, y, 0, 0 }; }
    // ...
    T x, y;
    // ...
};

【讨论】:

  • 谢谢。做到了。不敢相信我错过了。
【解决方案2】:

你有一个循环依赖。
您可以通过在一个“方向”上使用转换构造函数来解决它。
这个使用构造函数来增加维度,使用转换运算符来减少它们:

template <typename T>
class Vector2 {
    T x, y;
};

template <typename T>
class Vector3 {
    Vector3(const Vector2<T>& v2) : x(v2.x), y(v2.y), z(0) {}
    operator Vector2<T>() const { return { x, y }; }
    T x, y, z;
};

template <typename T>
class Vector4 {
    Vector4(const Vector2<T>& v2) : x(v2.x), y(v2.y), z(0), w(0) {}
    Vector4(const Vector3<T>& v3) : x(v3.x), y(v3.y), z(v3.z), w(0) {}
    operator Vector2<T>() const { return { x, y }; }
    operator Vector3<T>() const { return { x, y, z }; }
    T x, y, z, w;
};

(在此处插入有关隐式转换危险的严厉警告。)

【讨论】:

  • 虽然我将 François Andrieux 的答案标记为正确的答案(它似乎更像是一个前向声明而不是循环依赖问题),但我喜欢你的解决方案有一定的优雅,事实上,我可能最终会使用。谢谢你们俩。我也明确表示了转换,我 100% 同意。在使用其他人的代码时,我不止一次对意外的转换感到惊讶。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-11
相关资源
最近更新 更多