C++ 中可选的结构类型可能性或任何其他语言?

发布于 2024-09-04 00:19:17 字数 331 浏览 15 评论 0原文

在 C++ 中如何告诉编译器 Ogre::Vector3 IS_SAME_AS SomeOtherLIB::Vector3 ? 我觉得……在像 c++ 这样的语言中,它们不是结构类型的,但在某些情况下它是有意义的。

通常,作为游戏开发人员,在使用 4 个以上提供排序或自己的 Vector3 实现的库时。代码中充斥着 ToOgre、ToThis、ToThat 转换函数。这是大量的 Float3 复制,不应该首先发生。

在 C++ 或任何其他语言中,我们不必从一种类型转换(复制)到另一种类型,这本质上是相同的。但是 C++ 中的任何解决方案都适用于 C/C++,因为大多数优秀的游戏开发库都是针对 C/C++ 的。

In C++ how to tell compiler that Ogre::Vector3 IS_SAME_AS SomeOtherLIB::Vector3 ?
I feel that.. in languages like c++ which are not structural typed but there are cases when it makes sense.

Normally as game developer when working with 4+ libraries that provide sort or their own Vector3 implementation. The code is littered with ToOgre, ToThis, ToThat conversion function. Thats a lot of Float3 copying around which should not happen on first place.

Is in C++ or any other languages where we dont have to convert (copying) from one type to another which is essentially the samething. But any solution in C++ as most of the good gamedevs libs are for c/c++.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

茶色山野 2024-09-11 00:19:17

如果使用模板,则可以定义采用任何类型参数的函数,只要在该类型上定义了必要的操作即可。例子:

class Foo { void quack() {} };
class Bar { void quack() {} };
class Baz {};

template<typename Duck>
void f(Duck d) {
    d.quack();
}
int main() {
    f(Foo()); // works
    f(Bar()); // works
    f(Baz()); // compile error because Baz does not have a quack method
    return 0;
}

If you use templates you can define functions that take any type of argument as long as the necessary operations are defined on that type. Example:

class Foo { void quack() {} };
class Bar { void quack() {} };
class Baz {};

template<typename Duck>
void f(Duck d) {
    d.quack();
}
int main() {
    f(Foo()); // works
    f(Bar()); // works
    f(Baz()); // compile error because Baz does not have a quack method
    return 0;
}
养猫人 2024-09-11 00:19:17

虽然它不适合任何情况,但模板可以为您提供“编译时鸭子类型”。

假设您有两种向量类型:

struct Vec3A {
    float x, y, z;
};

struct Vec3B {
    float p[3];
};

您可以定义函数模板来隐藏如何获取组件的实现:

template<class T> float get_x(const T&);
template<class T> float get_y(const T&);
template<class T> float get_z(const T&);

template<> float get_x<Vec3A>(const Vec3A& v) { return v.x; }
// ...
template<> float get_x<Vec3B>(const Vec3B& v) { return v.p[0]; }
// ...

使用此类帮助程序,您现在可以编写适用于这两种向量的通用函数:

template<class T> float length(const T& t) {
    return std::sqrt(std::pow(get_x(t), 2), 
                     std::pow(get_y(t), 2),
                     std::pow(get_z(t), 2));
}

您还可以继续专门化实用程序,例如 length () 出于性能或其他原因,例如,如果某个向量已经有一个为您提供长度的成员函数:

template<> float length<Vec3C>(const Vec3C& v) {
    return v.length();
}

While it doesn't suit any situation, templates can give you "compile-time duck typing".

Lets say you have two vector types:

struct Vec3A {
    float x, y, z;
};

struct Vec3B {
    float p[3];
};

You can define function templates that hide the implementation how of to get the components:

template<class T> float get_x(const T&);
template<class T> float get_y(const T&);
template<class T> float get_z(const T&);

template<> float get_x<Vec3A>(const Vec3A& v) { return v.x; }
// ...
template<> float get_x<Vec3B>(const Vec3B& v) { return v.p[0]; }
// ...

With such helpers you can now write generic functions that work on both:

template<class T> float length(const T& t) {
    return std::sqrt(std::pow(get_x(t), 2), 
                     std::pow(get_y(t), 2),
                     std::pow(get_z(t), 2));
}

You can also continue by specializing utilities like length() for performance or other reasons, e.g. if a certain vector already has a member function providing you with the length:

template<> float length<Vec3C>(const Vec3C& v) {
    return v.length();
}
街角迷惘 2024-09-11 00:19:17

如果您确实确定是非虚拟结构,则可以执行reinterpret_cast。但是,最好:

  1. 执行如 sepp2k 所示的模板化包装函数
  2. 从其中一个向量继承并向另一个向量添加转换运算符
  3. 添加一个单独的 _cast 函数来执行转换

If you are really sure in case of non-virtual structures, you can do a reinterpret_cast. However, it's better to:

  1. do templated wrapper functions as shown by sepp2k
  2. inherit from one of the vectors and add a conversion operator to the other vector
  3. add a separate _cast function that does the conversion
意犹 2024-09-11 00:19:17

Haxe 是一种高度可移植的语言,具有完全可选的结构子类型:

typedef Vector3 = { x : double, y : double, z : double };

class FancyVector3 {
    public var x : double, y : double, z : double;

    function dot(Vector3 v) {
        return x * v.x + y * v.y + z * v.z;
    }

    function length() {
        return Math.sqrt(dot(this));
    }
}

Vector3 不仅是一个已经可用的结构,而且还充当结构其他类的接口。这样的 typedef 结构可以指定函数签名和字段。

Haxe 还有一个用于与 C++ 对话的 CFFI(尽管它仍然需要转换方法),并且已经存在一些 C++ 游戏引擎以及各种较低级别框架的绑定。用纯 Haxe 编写的跨平台引擎也在开发中,针对不同的 C++、Flash 和 JS(Canvas 和 WebGL)。

这可能不是您现在正在寻找的解决方案,但几年后可能会变得更有趣。

Haxe is a highly portable language with completely optional structural subtyping:

typedef Vector3 = { x : double, y : double, z : double };

class FancyVector3 {
    public var x : double, y : double, z : double;

    function dot(Vector3 v) {
        return x * v.x + y * v.y + z * v.z;
    }

    function length() {
        return Math.sqrt(dot(this));
    }
}

Not only is Vector3 an already usable structure, it also acts as a structural interface for other classes. Such typedef'd structs can specify function signatures as well as fields.

Haxe also has a CFFI for talking to C++ (although it still requires conversion methods), and bindings already exist for a few C++ game engines, as well as a variety of lower-level frameworks. Cross-platform engines written in pure Haxe are also being developed, targeting variously C++, Flash, and JS (both Canvas and WebGL).

This is probably not the solution you are looking for right now, but may become more interesting within a few years.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文