zos*_*ska 10 c++ templates g++ language-lawyer clang++
我有这个例子:
#include <iostream>
#include <tuple>
#include <string>
template <typename T>
class A {
public:
A(const T &t) : m_t(t) {}
void foo() {
std::cout << m_t << std::endl;
}
private:
T m_t;
};
typedef std::tuple<std::string, std::string> Type;
std::ostream &operator<<(std::ostream &os, const Type &t) {
os << std::get<0>(t) << " " << std::get<1>(t);
return os;
}
int main() {
A<Type> a(Type{"ala", " ma kota"});
a.foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
与clang ++(3.6)生成:
test_clang.cpp:10:19: error: call to function 'operator<<' that is neither visible in the template definition nor found by argument-dependent lookup
std::cout << m_t << std::endl;
^
test_clang.cpp:26:7: note: in instantiation of member function 'A<std::tuple<std::basic_string<char>, std::basic_string<char> > >::foo' requested here
a.foo();
^
test_clang.cpp:19:15: note: 'operator<<' should be declared prior to the call site
std::ostream &operator<<(std::ostream &os, const Type &t) {
Run Code Online (Sandbox Code Playgroud)
使用C++ 11和g ++ - 5.2.1使用C++ 17版本的g ++ - 4.8期间没有发生错误.铛++ - 3.6需求std::ostream &operator<<(std::ostream &os, const Type &t)
被定义之前 A::foo<T>
.
从我的观点来看,成员m_t
依赖于模板参数类型,并且operator<<
在模板定义期间不应该使用此类型.为什么clang有编译错误而g ++没有?
std::tuple<std::string, std::string>\n
Run Code Online (Sandbox Code Playgroud)\n\n让我们看看这种类型的关联命名空间。[basic.lookup.argdep]/(2.2):
\n\n\n\n\n它的关联命名空间是其关联类的最内层封闭命名空间。
\n
那将是命名空间std
或辅助命名空间,但肯定不是全局命名空间。
\n\n\n此外,如果
\nT
是类模板特化,则其关联的命名空间和类还包括:与为模板类型参数(不包括模板模板参数)提供的模板实参的类型关联的命名空间和类;[\xe2\x80\xa6 不适用规则\xe2\x80\xa6]
递归地应用上面的内容来为关联的命名空间std::string
提供命名空间std
(以及辅助命名空间)。当然不是全局命名空间。显然,可以对 重复相同的论证std::cout
,得出相同的结论。
因此,ADL 不会在全局命名空间中查找,而这正是在.
\n\n最后,根据 [temp.dep.candidate]/1,名称解析不成功:
\n\n\n\nGCC 在这里表现得不合规;请参阅#51577。
\n 归档时间: |
|
查看次数: |
374 次 |
最近记录: |