[英]Why doesn't std::tie work with const class methods?
#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;
}
I'm trying to create a class for storing the date (year, month, day).我正在尝试创建一个用于存储日期(年、月、日)的类。 In order to use this class in a map, I want to overload the comparison operator.
为了在地图中使用这个类,我想重载比较运算符。 Unfortunately, the code above does not work.
不幸的是,上面的代码不起作用。 The compiler gives me an error
编译器给我一个错误
error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'|
The error apparently occurs in tie
function.错误显然发生在
tie
函数中。 Once I change it to make_tuple
everything compiles and works.一旦我将其更改为
make_tuple
一切都会编译并运行。 I also checked that if I declared variables year
, month
and day
as public I could write something like我还检查了如果我将变量
year
, month
和day
为 public 我可以写类似的东西
auto lhs = tie(lhs.year, lhs.month, lhs.day);
and this would also work.这也行。
I don't understand why.我不明白为什么。 Does anyone have ideas?
有没有人有想法?
Your member functions return copy of the members(aka temprory rvalue ), and std::tie
has argument list, which try to bind by non-cost lvalue ref .您的成员函数返回成员的副本(又名临时rvalue ),并且
std::tie
具有参数列表,它尝试通过非成本左值 ref进行绑定。
template< class... Types >
constexpr std::tuple<Types&...> tie( Types&... args ) noexcept;
// ^^^^^^^^^^^^^^^^
This is simply not possible as per standard , hence the error! 根据标准,这根本不可能,因此出现错误!
The std::make_tuple
on the other hand has forwarding reference .另一方面,
std::make_tuple
具有forwarding reference 。 Therefore, no issues.因此,没有问题。
template< class... Types >
std::tuple<VTypes...> make_tuple( Types&&... args );
// ^^^^^^^^^^^^^^^^
When the members are public, they became lvalues.当成员是 public 时,它们就变成了左值。
I would suggest, make the operator<
friend of the class instead.我建议,让
operator<
成为班级的朋友。
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;
};
The entire purpose of std::tie is to create a tuple of lvalue references. std::tie的全部目的是创建一个左值引用的元组。 Your member functions return
int
which aren't lvalues, and so you get an error.您的成员函数返回不是左值的
int
,因此您会收到错误消息。
Making the member variables public and using them directly as arguments to tie
works because variables are lvalues.公开成员变量并直接使用它们作为
tie
参数是有效的,因为变量是左值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.