【发布时间】:2020-03-25 13:53:54
【问题描述】:
我最近发现一个大型项目在经常包含的头文件和全局命名空间中有一个“using namespace std::rel_ops;”。哎哟。
具体来说,因为这两个函数模板声明不明确,导致了一个问题:
namespace std::rel_ops {
template <class T>
bool operator!=(const T&, const T&);
}
namespace std {
template <class... TTypes, class... UTypes>
constexpr bool operator!=(const tuple<TTypes...>&, const tuple<UTypes...>&);
}
所以我尝试使用类似于std::tie(a.m1, a.m2, a.m3) != std::tie(b.m1, b.m2, b.m3) 的表达式是错误的。
所以计划是删除using namespace std::rel_ops;,然后修复导致的编译器错误,可能通过定义更具体的比较运算符函数。但我还想评估一下这种更改是否有可能改变隐藏在这个大型项目中其他地方的某些代码的含义,而不会导致编译器错误。
在什么情况下(如果有的话),两个带有和不带有指令 using namespace std::rel_ops; 的 C++ 程序的行为会有所不同,因为两者都不是格式错误且需要诊断?
我怀疑它需要另一个比较运算符函数模板,它比std::rel_ops 中的一个更少 专门化,并且具有与std::rel_ops 定义不同的有效行为。这两种情况在实际项目中似乎不太可能,更不可能一起考虑。
【问题讨论】:
-
好吧,由于 ADL,我认为在专门针对某些外部类型的情况下,删除
using namespace可能会产生相当广泛的古怪错误 -
@bartop 是的,但我认为删除指令只能缩小而不是扩大可行的功能集,这限制了可能出错的地方。不过,我还没有经过更仔细的证明。 (我可能会稍后尝试,看看我是否可以自我回答,如果其他人没有先给出好的答案。)
-
如果有的话,两个 C++ 程序在什么情况下可以使用命名空间 std::rel_ops;考虑到两者都不是符合要求的诊断格式,因此行为不同? 想到了重载解决方案。如果 using 指令带来更好的重载,则将使用该指令。删除指令将删除重载,这将改变调用哪个函数。
-
@NathanOliver 而且没有多少潜在的声明可能比
rel_ops中的任何东西都更糟糕,对吧? -
@aschepler
template <typename T, typename U> bool operator==(const T&, const U&)也许?
标签: c++ language-lawyer comparison-operators