【问题标题】:Implicit conversion between templates模板之间的隐式转换
【发布时间】:2017-05-31 10:36:14
【问题描述】:

我不太明白为什么这里的代码不能编译。 应该可以像这样调用 dist() :

dist(GenericVec2<T>,GenericVec3<T>)

(无论这多么可怕)。这个想法是 GenericVec3 参数被转换运算符隐式转换为 GenericVec2。 我在这里找到了这个问题

C++ implicit type conversion with template

,但我不确定它是否可以应用于我的问题(将转换运算符设置为“friend”不起作用)。 VS输出如下错误:

error C2672: 'dist': no matching overloaded function found
error C2784: 'F dist(const GenericVec2<F> &,const GenericVec2<F> &)': could not deduce template argument for 'const GenericVec2<F> &' from 'Vec3'
note: see declaration of 'dist'

这是我的代码:

#include <iostream>

template<typename F> struct GenericVec2
{
    GenericVec2<F>::GenericVec2(F _x = 0, F _y = 0) : x(_x), y(_y) {}

    F x;
    F y;
};
using Vec2 = GenericVec2<float>;

template<typename F> struct GenericVec3
{
    GenericVec3<F>::GenericVec3(F _x = 0, F _y = 0, F _z = 0) : x(_x), y(_y), z(_z) {}

    operator GenericVec2<F>()               { return *reinterpret_cast<GenericVec2<F>*>(&x); }
    operator const GenericVec2<F>() const   { return *reinterpret_cast<const GenericVec2<F>*>(&x); }

    F x;
    F y;
    F z;
};
using Vec3 = GenericVec3<float>;

template<typename F> F dist(const GenericVec2<F>& a, const GenericVec2<F>& b)
{
    return std::hypot(a.x - b.x, a.y - b.y);
}

int main()
{
    Vec2 a{ 2.0f, 3.0f };
    Vec3 b{ 1.0f, 1.0f, 1.0f };
    Vec2 c = b;

    float d = dist(a, Vec2{ b });   // works
    float e = dist(a, b);           // doesn't compile

    std::cin.ignore();

    return 0;
}

提前致谢!

-托马斯

【问题讨论】:

  • 您的reinterpret_cast 打破了严格的别名并从union 成员中读取,而不是最后分配给的成员也是UB。把那个代码扔掉,从头开始,它已经坏得无法修复了。如果你不明白我为什么这么说,是时候读一本好书了。
  • 我不能,这不是我的代码,也不容易交换。我只需要知道如何编译它(最好不要进行明确的dist(a, Vec2{b}) 转换。
  • 我已经删除了联合,因为它不是实际问题的一部分(而且确实不是很漂亮)。最初的问题仍然存在。
  • 如果我在第一条评论中不清楚:此代码完全不正确且非法。让它编译不会让它变得更好根本。此代码不能用于生产、POC 或玩具程序。 (在 union 被删除后仍然适用,请参阅严格别名。)
  • 您不能将用户定义的隐式转换与模板参数推导结合起来。 dist&lt;float&gt;(a, b) 也应该可以工作。

标签: c++ templates implicit-conversion conversion-operator


【解决方案1】:

问题是,在

template<typename F> F dist(const GenericVec2<F>& a, const GenericVec2<F>& b)

你不能从GenericVec2&lt;float&gt; 推导出第二个参数。 一种解决方案是通过friend 使函数成为非模板:

template<typename F> struct GenericVec2
{
    GenericVec2<F>::GenericVec2(F _x = 0, F _y = 0) : x(_x), y(_y) {}


    friend F dist(const GenericVec2& a, const GenericVec2& b)
    {
        return std::hypot(a.x - b.x, a.y - b.y);
    }

    F x;
    F y;
};

【讨论】:

  • 成功了!得看看friend关键字,我猜...
【解决方案2】:

为了使隐式转换成为可能,目标类应具有一个构造函数,该构造函数接收源类型(或可从源类型转换的类型)作为参数。 GenericVec3 中定义的转换运算符用于显式转换操作。

所以你应该在 GenericVec2 类中定义以下构造函数

GenericVec2(const GenericVec3&lt;F&gt;&amp; v3) { ... }

【讨论】:

猜你喜欢
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
相关资源
最近更新 更多