C++17结构体中提取std::tie为独立成员函数实现operator<的正确性及相关疑问
关于你这段C++17结构体代码的疑问解答
咱们一步步来拆解你的问题,逐个给出明确的答案:
1. 代码是否正确?
这段代码是正确的,前提是M1、M2、M3这三个类型都已经正确实现了<运算符(因为std::tuple的<会按成员顺序依次调用每个元素的<进行比较)。
2. S::tie()返回的是成员引用还是拷贝?
S::tie()返回的是由成员的const引用组成的元组,完全不会拷贝m1、m2、m3。
原因是:std::tie的特性是接收左值参数,并返回包含对应左值引用的tuple;而在const成员函数tie()中,m1、m2、m3都是const左值,所以std::tie(m1,m2,m3)会生成std::tuple<const M1&, const M2&, const M3&>类型的对象,仅持有成员的引用。
3. auto能否推导出正确的引用元组类型?
完全可以。C++17的auto会精确推导std::tie返回的tuple类型,也就是上面提到的带const引用的tuple类型,没有任何问题。
4. const限定符是否起到了正确的作用?
是的,const限定符用得非常合理:
operator<本身是const成员函数,意味着它不能修改当前对象的状态,也只能接收const的参数对象that。tie()作为const成员函数,访问到的m1、m2、m3都是const的,因此生成的tuple引用也是const的,完全符合比较操作的只读需求,避免了意外修改成员的风险。
为什么常见示例都直接调用两次std::tie,而非提取成独立成员函数?
常见示例采用直接写法主要有几个原因:
- 代码简洁性:对于简单结构体,直接写
std::tie(m1,m2,m3) < std::tie(that.m1, that.m2, that.m3)更紧凑,不需要额外定义成员函数。 - 直观性:新手更容易直接理解比较逻辑是按成员顺序依次比较,不需要跳转看tie()函数的实现。
- 习惯使然:多数教程会用最小化的代码展示功能,直接写法更符合这种场景。
不过你的写法其实有明显优势:如果后续需要实现其他比较运算符(比如operator==、operator<=),或者有其他地方需要用到这个成员的tuple组合,提取成tie()成员函数可以复用代码,后续修改成员(比如新增m4)时,只需要修改tie()函数一次即可,维护性更好。
内容的提问来源于stack exchange,提问作者Andrew Tomazos
相关产品推荐
相关产品推荐

