【问题标题】:Why doesn't std::tie work with const class methods?为什么 std::tie 不能与 const 类方法一起使用?
【发布时间】:2021-12-25 06:54:02
【问题描述】:
#include <string>
#include <tuple>
#include <stdexcept>
using namespace std;

class Date
{
    public:
        Date() {};
    Date(int new_year, int new_month, int new_day)
    {
        year = new_year;

        if ((new_month < 1) || (new_month > 12))
        {
            throw runtime_error("Month value is invalid: " + to_string(new_month));
        }
        month = new_month;

        if ((new_day < 1) || (new_day > 31))
        {
            throw runtime_error("Day value is invalid: " + to_string(new_day));
        }
        day = new_day;
    }

    int GetYear() const
    {
        return year;
    }

    int GetMonth() const
    {
        return month;
    }

    int GetDay() const
    {
        return day;
    }

    private:
        int year;
    int month;
    int day;
};

bool operator < (const Date &lhs, const Date &rhs)
{
    auto lhs = tie(lhs.GetYear(), lhs.GetMonth(), lhs.GetDay());
    auto rhs = tie(rhs.GetYear(), rhs.GetMonth(), rhs.GetDay());

    return lhs < rhs;
}

我正在尝试创建一个用于存储日期(年、月、日)的类。为了在地图中使用这个类,我想重载比较运算符。不幸的是,上面的代码不起作用。编译器给我一个错误

error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'|

错误显然发生在tie 函数中。一旦我将其更改为make_tuple,一切都会编译并运行。我还检查了如果我将变量 yearmonthday 声明为 public,我可以写类似

auto lhs = tie(lhs.year, lhs.month, lhs.day);

这也可以。

我不明白为什么。有人有想法吗?

【问题讨论】:

  • 我现在无法阅读代码,但从您提到的错误来看 - 将引用绑定到非const 临时是不行的。

标签: c++ class c++11 tuples member-functions


【解决方案1】:

std::tie 的全部目的是创建一个左值引用的元组。您的成员函数返回不是左值的 int,因此您会收到错误。

公开成员变量并将它们直接用作tie 的参数是可行的,因为变量是左值。

【讨论】:

    【解决方案2】:

    您的成员函数返回成员的副本(又名 temprory rvalue),并且std::tie 具有参数列表,它尝试通过 non-cost lvalue ref 进行绑定。

    template< class... Types >
    constexpr std::tuple<Types&...> tie( Types&... args ) noexcept;
    //                                  ^^^^^^^^^^^^^^^^
    

    这个is simply not possible as per standard,因此错误!


    另一方面,std::make_tuple 具有转发参考。因此,没有问题。

    template< class... Types >
    std::tuple<VTypes...> make_tuple( Types&&... args );
    //                               ^^^^^^^^^^^^^^^^
    

    当成员公开时,它们成为左值。


    我建议,改为让 operator&lt; 成为班级的朋友。

    class Date 
    {
    public:
      // .... other code
      friend bool operator<(const Date& lhs, const Date& rhs) noexcept
      {
        return std::tie(lhs.year, lhs.month, lhs.day) < std::tie(rhs.year, rhs.month, rhs.day);
      }
    
    private:
      int year;
      int month;
      int day;
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-14
      • 2018-02-25
      • 2018-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多