代码之家  ›  专栏  ›  技术社区  ›  darune

对或元组值的名称别名引用

  •  1
  • darune  · 技术社区  · 7 年前

    当重新构造某些代码时,我在返回具有2个值的结构时遇到了一个“问题”。现在,应该根据记录的效果来命名它们。后来我想用 tie 所以我把结构改为继承自 std::pair 只是设置参考。现在这实际上很好,但是你会注意到,现在我的结构的大小是24,相比之下只有8。

    #include <tuple>
    
    
    struct Transaction : public std::pair<int, int> {
        using pair::pair;
    
      int& deducted = first;
      int& transfered = second;
    };
    //static_assert(sizeof(Transaction) == sizeof(std::pair<int, int>));//commenting in this line will fail compilation
    
    Transaction makeTheTransaction();
    
    void test(int& deduct, int& transfer) {
        std::tie(deduct, transfer) = makeTheTransaction(); 
    }
    

    可能很明显的方法是转换成成员函数,但是对于这种情况,这也太多了“样板文件”(这样就更容易不使用了) 领带 稍后)。一个直接的memcpy是对例如一个tuple是向前的ub。直接结构化绑定也是不可行的,因为变量已经在使用中。

    我的问题是,什么是更好或最小的代码解决方案,而忽略了可重用的部分(并且考虑到大小不应超过2个整数)?

    更新:在这种情况下,我最终只做了一个简单的结构,并在临时保存返回。对于来到这里的其他用户,有一个要提升的库建议,它似乎能够将任何结构转换为元组: https://github.com/apolukhin/magic_get/

    3 回复  |  直到 7 年前
        1
  •  1
  •   Peter Ruderman    7 年前

    我觉得你把问题搞得太复杂了。如果你需要使用 std::tie 你可以用它。不需要改变你的结构:

    struct Transaction
    {
      int deducted;
      int transferred;
    };
    
    // later...
    
    auto t = std::tie(transaction.deducted, transaction.transferred);
    

    如果这是您经常使用的模式,那么您可以用一个小助手方法来包装它:

    struct Transaction
    {
      int deducted;
      int transferred;
    
      auto to_tuple() const
      {
        return std::tie(deducted, transferred);
      }
    };
    

    您也可以使用它一次分配给多个变量,尽管我强烈反对这样做。它容易出错,导致代码脆弱。(例如,如果您颠倒 deduct transfer 在下面的示例中,您有一个bug,但是编译器不会给出任何警告或错误。)

    void test(int& deduct, int& transfer)
    {
      std::tie(deduct, transfer) = makeTheTransaction().to_tuple();
    }
    

    编辑:第二次思考…

    如果这里的目标只是简单地将结构分解为变量,那么可以直接这样做,并避免使用对或元组:

    struct Transaction
    {
      int deducted;
      int transferred;
    
      void decompose(int* deducted_, int* transferred_)
      {
        *deducted_ = deducted;
        *transferred_ = transferred;
      }
    };
    
    void test(int& deduct, int& transfer)
    {
      makeTheTransaction().decompose(&deduct, &transfer);
    }
    

    这仍然是脆弱的,但至少现在,当您将调用写入 decompose 方法,这将使模式不太容易出错。

        2
  •  0
  •   Jarod42    7 年前

    我只想说:

    struct Transaction
    {
        int deducted;
        int transfered;
    };
    

    用法类似于:

    Transaction makeTheTransaction() { return {4, 2}; }
    
    int main()
    {
        auto [deduct, transfer] = makeTheTransaction(); 
        std::cout << deduct << transfer << std::endl;
    }
    

    Demo

        3
  •  0
  •   felix    7 年前

    添加转换函数可以:

    #include <tuple>
    
    struct Transaction {
        std::pair<int, int> data_;
    
        operator std::tuple<int &, int &> () {
            return std::tie(data_.first, data_.second);
        }
    };
    static_assert(sizeof(Transaction) == sizeof(std::pair<int, int>));
    
    Transaction makeTheTransaction() {
        return Transaction();
    }
    
    void test(int& deduct, int& transfer) {
        std::tie(deduct, transfer) = makeTheTransaction();
    }
    

    我认为在与std::tie一起使用时,这不会导致任何终身问题。

    这个 Transaction 不适用于具有两个标识符的结构化绑定。但是您可以通过专门化使它支持“tuple-like”绑定 std::get std::tuple_size 为了它。