C++语义类型包装

发布于 2024-11-16 01:00:19 字数 392 浏览 0 评论 0原文

我有一个数据类型,例如 class Vector3。现在我需要创建几个与 Vector3 具有相同接口的类,但具有更高级别的语义(例如:PositionVelocity)。使用 typedef 是不够的,因为我需要这些类型是不同的,以便它们可以用于重载。在 C++0x 中,我可能可以使用构造函数继承:

struct Position: public Vector3 {
    using Vector3::Vector3;
};

这会有什么问题吗?有没有更好的办法呢?是否可以在不使用 C++0x 功能且不必显式编写所有 Vector3 构造函数的情况下完成此操作?

I have a data type for example class Vector3. Now I need to create several classes with same interface as Vector3, but with higher level semantic (for example: Position, Velocity). Using typedef is not enough, because I need these types to be distinct so that they can be used for overloading. In C++0x I could probably use constructor inheritance:

struct Position: public Vector3 {
    using Vector3::Vector3;
};

Could there be any problems with this? Is there any better way to do it? Is it possible to do it without using C++0x features and not having to explicitly write all Vector3 constructors?

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

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

发布评论

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

评论(2

心病无药医 2024-11-23 01:00:19

考虑使用标记结构

struct tagPosition {};
struct tagDirection {};
struct tagGeneric {};

namespace detail
{
    template <typename Tag=tagGeneric>
        class Vector3
    {
        // business as usual
    };
}

typedef detail::Vector3<tagPosition>  Position;
typedef detail::Vector3<tagDirection> Direction;
typedef detail::Vector3<tagGeneric>   Vector3;

为了获得奖励积分,请使用转换运算符/构造函数:

    template <typename Tag=tagGeneric>
        class Vector3
    {
        template <typename OtherTag>
            explicit Vector3(const Vector3<OtherTag>& rhs) { /* ... */ }

//      template <typename OtherTag>
//            operator Vector3<OtherTag>() const { return /* ... */ }
    };

如果您喜欢危险地生活,则可以删除 explicit 关键字,或启用隐式转换运算符。这将具有能够启用混杂运算符解析的“好处”,如下所示:

 Position pos;
 Direction dir;
 Generic gen;

 dir = gen + pos; // you see why I call it 'promiscuous'?

我建议(相反)为这样的情况定义显式运算符(自由函数) :)

 Position operator+(const Position& v, const Translation& d) { /* .... */ }

这样你的类模型就可以反映你的类的语义。

C++0x 可能包含启用显式转换运算符的内容,IIRC:

在转换构造函数的情况下,您可以通过将构造函数声明为显式来禁用隐式转换 N1592 提案 将此关键字的语义扩展到所有转换运算符。显式声明的转换运算符不会执行隐式转换。相反,程序员必须显式调用它

Consider using a tag struct

struct tagPosition {};
struct tagDirection {};
struct tagGeneric {};

namespace detail
{
    template <typename Tag=tagGeneric>
        class Vector3
    {
        // business as usual
    };
}

typedef detail::Vector3<tagPosition>  Position;
typedef detail::Vector3<tagDirection> Direction;
typedef detail::Vector3<tagGeneric>   Vector3;

For bonus points, have conversion operators/constructors:

    template <typename Tag=tagGeneric>
        class Vector3
    {
        template <typename OtherTag>
            explicit Vector3(const Vector3<OtherTag>& rhs) { /* ... */ }

//      template <typename OtherTag>
//            operator Vector3<OtherTag>() const { return /* ... */ }
    };

If you like to live dangerously you can drop the explicit keyword, or enable the implicit conversion operator. This would have the 'benefit' of being able to enable promiscuous operator resolutions like so:

 Position pos;
 Direction dir;
 Generic gen;

 dir = gen + pos; // you see why I call it 'promiscuous'?

I'd recommend (instead) to define explicit operators for cases like this (free functions:)

 Position operator+(const Position& v, const Translation& d) { /* .... */ }

That way your class model reflects the semantics of your classes.

C++0x would possibly contain things to enable explicit conversion operators, IIRC:

In the case of converting constructors, you can disable implicit conversions by declaring the constructor as explicit The N1592 proposal stretches the semantics of this keyword to all conversion operators. A conversion operator declared explicit will not perform an implicit conversion. Instead, the programmer will have to call it explicitly

薄暮涼年 2024-11-23 01:00:19

当我需要不同但相似的类型时,我通常使用虚拟模板参数,例如(即兴的,不受编译器的脏手影响)

template< class UniqueId >
struct Blah {};

typedef Blah< struct AlphaId > Alpha;
typedef Blah< struct BetaId > Beta;

这可能是也可能不是您需要的。

干杯&呵呵,

When I've needed distinct-but-similar types I've generally used a dummy template parameter, like (off the cuff, untouched by compiler's dirty hands)

template< class UniqueId >
struct Blah {};

typedef Blah< struct AlphaId > Alpha;
typedef Blah< struct BetaId > Beta;

This may or may not be what you need.

Cheers & hth.,

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