【问题标题】:How can I keep 'first' and 'second' replacing std::pair with struct?如何保持“第一”和“第二”用结构替换 std::pair?
【发布时间】:2019-04-17 07:21:54
【问题描述】:

我有一对std::pair<int, long>,并且在不同地方的代码中使用pr.firstpr.second(还有ppr->firstppr->second)类型的符号。 现在我想将pair更改为结构,

struct ABC 
{
    int a;
    long b;
};

有没有办法可以在代码中保留这些“第一”和“第二”符号来访问这个结构?也许创建一个函数?

【问题讨论】:

  • 你的结构中只能有公共成员firstsecond
  • 但由于代码可读性问题,我无法命名它们的第一个和第二个
  • std::pair 的工作方式是调用其成员firstsecond;这不是特殊语法。

标签: c++ struct std-pair


【解决方案1】:

抛开您想要这样做的原因(在没有任何其他信息的情况下至少可以说是有问题的),最简单的方法是使用

struct ABC
{
    int first;
    long second;
};

但如果您希望成员被称为其他名称​​并且您不想诉诸“getter”函数(这将需要在调用站点使用括号),一个解决方案是使用成员变量的引用:

struct ABC {
    int a;
    long b;

    int& first;
    long& second;

    ABC() : first(a), second(b) {}
};

但是如果你采用这个,你需要自己编写属于“5 规则”的构造函数来正确绑定引用,否则看似平淡无奇的复制或移动将不起作用。

尽管这个答案展示了 C++ 的强大功能,但该语言以其允许您自爆的能力而闻名。尽管解决方案可能很花哨,但在您的代码库甚至语言本身的演变中引入奇怪错误的可能性怎么强调都不为过。因此,这应该被认为是一种反模式,并且只在真正例外的情况下使用。

【讨论】:

  • 一般来说,您不能重新绑定参考。特别是,如果您的赋值运算符说(例如)a = other.a,那么first 也会自动采用新值。您唯一需要重新绑定引用的情况是您尝试 memcpy 类型。
  • @Resurrection:现在最好的办法就是让std::pair保持原样。
  • @Bathsheba 完全同意。 :-)
  • 我可以在关于“5 规则” 的声明中划掉。我最近有一个糟糕的经历(当我在我的生产代码中使用这样的东西时)。当我对复制构造函数进行模板化时,突然隐式生成了默认的复制构造函数(我不知道)并做了坏事。 ;-)
  • @Scheff:我也有同样糟糕的回忆!
【解决方案2】:

你可能想试试这个:

struct ABC 
{
    union {
        int a;
        int first;
    };
    union {
        long b;
        long second;
    };
};

这允许您使用afirst 以及bsecond 可互换。 不过最好替换 firstsecond 的用法以避免混淆。

正如所指出的,这是 undefined behaviour 12.3 Unions 但至少可以与 MSVC 和 GCC 一起使用。 感谢cmets

【讨论】:

  • 访问联合成员而不是用于初始化是未定义的行为
  • 从技术上讲,这是 C++ 中的 UB(尽管它是在 C 中定义的)。尽管我认为大多数 C++ 编译器都会编译它,尤其是那些据称“支持”C(例如 MSVC)的编译器。如果您充分否认,我会投票赞成,因为这是一个巧妙的解决方案。
  • 应该注意 gcc documents 允许通过联合进行类型双关语,即使 -fstrict-aliasing 开启。但它并没有明确地将其记录为 C++ 扩展......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-16
  • 2021-09-15
  • 2013-05-05
相关资源
最近更新 更多