Bil*_*Won 6 c++ tuples std c++11
我很好奇为什么这段代码不起作用:
#include "stdafx.h"
#include <iostream>
#include <tuple>
#include <string>
#include <vector>
#include <algorithm>
typedef std::tuple<int, std::string> intString;
bool operator<(intString& lhs, intString& rhs){
return std::tie(std::get<1>(lhs), std::get<0>(lhs)) < std::tie(std::get<1>(rhs), std::get<0>(rhs));
}
void printIntStrings(std::vector<intString>& v){
for (intString& i : v){
std::cout << std::get<0>(i) << " is " << std::get<1>(i) << std::endl;
}
}
int main(int argc, char* argv[])
{
std::vector<intString> v;
v.push_back(std::make_tuple(5, "five"));
v.push_back(std::make_tuple(2, "two"));
v.push_back(std::make_tuple(9, "nine"));
printIntStrings(v);
std::sort(v.begin(), v.end());
printIntStrings(v);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
据我所知,我只是创建一个intStrings向量,我的运算符应该首先按元组中的第二个元素排序,因此输出应该是(最后3行)
5 five
9 nine
2 two
Run Code Online (Sandbox Code Playgroud)
无论如何在我的机器上运行它
2 two
5 five
9 nine
Run Code Online (Sandbox Code Playgroud)
这意味着排序使用默认的小于运算符,忽略我指定的那个.注意,在参数之前添加const似乎不会影响任何东西.
我发现了三种"修复"这种方法.
修复#1
环绕bool运算符<...在命名空间std中如下:
namespace std{
bool operator<(intString& lhs, intString& rhs){
return std::tie(std::get<1>(lhs), std::get<0>(lhs)) < std::tie(std::get<1>(rhs), std::get<0>(rhs));
}
}
Run Code Online (Sandbox Code Playgroud)
但是我被告知我们永远不应该向std命名空间添加内容,因为该行为是未定义的,所以这个修复似乎是最糟糕的.
修复#2
像这样在元组中添加一些自定义内容:
enum class TRASH{DOESNTMATTER};
typedef std::tuple<int, std::string, TRASH> intString;
bool operator<(intString& lhs, intString& rhs){
return std::tie(std::get<1>(lhs), std::get<0>(lhs)) < std::tie(std::get<1>(rhs), std::get<0>(rhs));
}
Run Code Online (Sandbox Code Playgroud)
(并且显然将TRASH :: DOESNTMATTER添加为第三个make_tuple参数)但是,对于这么简单的事情来说,这看起来似乎很多.此外,它似乎是浪费,因为枚举没有被有意义地使用.
修复#3
像这样使用谓词排序:
std::sort(v.begin(), v.end(), operator<);
Run Code Online (Sandbox Code Playgroud)
这似乎是最优雅的解决方案.但是,我不明白为什么我必须明确告诉编译器使用我定义的运算符<.
所以我想知道:
1)为什么会这样?c ++不应该找到我的实现并使用它吗?
2)哪个"修复"最好?如果我找不到的那个,你会推荐什么?
有任何想法吗?谢谢阅读!
在您使用的位置(在它的主体和/或其中调用的任何辅助函数,某处)中,您的operator<重载是不可见的.<std::sort<algorithm>
如果要使用它,必须通过依赖于参数的查找来获取它; 但是没有任何内容std::tuple<int, std::string>将全局命名空间作为关联的命名空间,因此ADL也不会帮助您,并且使用标准命名空间.
将它作为比较器传递,最好使用lambda或函数对象(内联比函数指针更好),是最简单的修复.我也建议重命名它; 具有operator<与标准语义完全不同的语义的重载,表达式可能会或可能不会a < b根据表达式的位置使用,这不是一个好主意.