为什么 std::tie 不能与 const class 方法一起使用?
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;
}
我正在尝试创建一个 class 来存储日期(年、月、日)。为了在地图中使用这个 class ,我想重载比较运算符。不幸的是,上面的代码不起作用。编译器给我一个错误
error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'|
错误显然发生在 tie
函数中。一旦我将其更改为 make_tuple
一切都会编译并运行。我还检查了如果我将变量 year
、month
和 day
声明为 public 我可以写类似
的东西
auto lhs = tie(lhs.year, lhs.month, lhs.day);
这也行。
我不明白为什么。有人有想法吗?
std::tie 的全部目的是创建左值引用的元组。你的成员函数 return int
不是左值,所以你得到一个错误。
创建成员变量 public 并直接将它们用作 tie
的参数,因为变量是左值。
你的成员函数 return 成员的副本(又名临时 rvalue),并且 std::tie
有参数列表,它试图通过 非成本左值 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 );
// ^^^^^^^^^^^^^^^^
当成员是 public 时,它们变成了左值。
我建议,改为 class 的 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;
};
#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;
}
我正在尝试创建一个 class 来存储日期(年、月、日)。为了在地图中使用这个 class ,我想重载比较运算符。不幸的是,上面的代码不起作用。编译器给我一个错误
error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'|
错误显然发生在 tie
函数中。一旦我将其更改为 make_tuple
一切都会编译并运行。我还检查了如果我将变量 year
、month
和 day
声明为 public 我可以写类似
auto lhs = tie(lhs.year, lhs.month, lhs.day);
这也行。
我不明白为什么。有人有想法吗?
std::tie 的全部目的是创建左值引用的元组。你的成员函数 return int
不是左值,所以你得到一个错误。
创建成员变量 public 并直接将它们用作 tie
的参数,因为变量是左值。
你的成员函数 return 成员的副本(又名临时 rvalue),并且 std::tie
有参数列表,它试图通过 非成本左值 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 );
// ^^^^^^^^^^^^^^^^
当成员是 public 时,它们变成了左值。
我建议,改为 class 的 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;
};