以下代码段是正确的C ++代码吗?
#include <sstream>
class Foo;
std::ostream& operator<<(std::ostream& str, Foo x); // (A)
namespace test {
class Message {
public:
std::ostringstream str;
};
template<typename T>
Message& operator<<(Message& m, T& t)
{
using ::operator<<;
m.str << t;
return m;
}
}
namespace detail {
class Class {
public:
int i;
Class() : i(5) {}
};
}
std::ostream& operator<<(std::ostream& str, detail::Class& myClass) { // (B)
return str << myClass.i;
}
int main() {
test::Message m;
detail::Class c;
m << c;
}
根据http://goo.gl/NkPNau的说法,GCC可以很好地进行编译,而Clang找不到operator<<
(B)。
如果你想知道:这是从使用GTEST使用自定义代码operator<<
对std::set
打印好的断言消息。除了将operator<<
(B)放在std名称空间中之外,我们无法找到一种使其与clang一起工作的方法(是的,我知道...)。
铛在这里是正确的。让我们将g ++的行为称为语言扩展。
确实适用依赖参数的查找(又名Koenig查找),因为m.str << t
使用最佳重载匹配m.str.operator<<(t)
或进行解释operator<<(m.str, t)
,并且第二种情况是函数名称为非限定ID。但:
14.6.4.2:
对于依赖于模板参数的函数调用,使用常规查找规则(3.4.1、3.4.2、3.4.3)找到候选函数,除了:
对于使用非限定名称查找(3.4.1)或限定名称查找(3.4.3)的查找部分,只能从模板定义上下文中找到函数声明。
对于使用关联的名称空间(3.4.2)进行的查找,仅会找到在模板定义上下文或模板实例化上下文中找到的函数声明。
如果函数名称是一个非限定ID,并且在关联的名称空间中进行查找时考虑了所有转换单元中这些名称空间中引入的具有外部链接的所有函数声明,则调用的格式可能不正确或匹配会更好在模板定义和模板实例化上下文中找到那些声明,则程序具有未定义的行为。
在模板定义上下文中,(B)不可见。(B)在模板实例化上下文中可见,但是全局名称空间不是std::ostringstream
或的关联名称空间detail::Class
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句