C++ 匿名命名空间内运算符的模板重载解析
简短问题:操作员是否有特殊的模板查找规则,用于通过内部链接进行重载解析,或者底部的代码是否是GCC中操作员的模板重载解析错误 细节:我不粘贴一段代码,而是让您了解我的推理。让我们从一些简单的代码开始:C++ 匿名命名空间内运算符的模板重载解析,c++,templates,gcc,language-lawyer,argument-dependent-lookup,C++,Templates,Gcc,Language Lawyer,Argument Dependent Lookup,简短问题:操作员是否有特殊的模板查找规则,用于通过内部链接进行重载解析,或者底部的代码是否是GCC中操作员的模板重载解析错误 细节:我不粘贴一段代码,而是让您了解我的推理。让我们从一些简单的代码开始: #include <iostream> template<typename T> struct A{ T b; }; struct B{}; template<typename T> void foo (const A<T>&a) {
#include <iostream>
template<typename T> struct A{ T b; };
struct B{};
template<typename T>
void foo (const A<T>&a) { foo(a.b); }
void foo (const B&) { std::cout << "hello"; }
int main(){
A<B> b;
foo(b);
}
代码现在无法编译。Clang表示错误:对函数“foo”的调用在模板定义中既不可见,也无法通过参数相关查找找到该函数
和GCC模板参数推断/替换失败
这是因为foo(const B&)
是在foo
之后定义的,并且没有外部链接,如中所述:
[基本链接]
未命名命名空间或在未命名命名空间中直接或间接声明的命名空间
内部联系。所有其他名称空间都有外部链接
[温度点]
依赖于模板参数的表达式的实例化上下文是一组声明
在同一翻译单元中的模板专用化实例化点之前声明外部链接
[临时副总裁候选人]
对于后缀表达式为从属名称的函数调用,
使用常用的查找规则(3.4.1,
3.4.2)但以下情况除外:
- 对于使用非限定名称查找(3.4.1)的查找部分,仅限模板中的函数声明 找到定义上下文
- 对于查找部分,请使用 关联的名称空间(3.4.2),仅在 模板定义上下文或模板实例化 可以找到上下文
struct ostream {} cout;
template<typename T> struct A{ T t; };
struct B{};
namespace {
template<typename T>
ostream& operator<< (ostream& out, const A<T>&v)
{ return out << v.t; }
ostream& operator<< (ostream& out, const B&)
{ return out; }
}
int main(){
A<B> a;
cout << a;
}
struct ostream{}cout;
模板结构A{T;};
结构B{};
名称空间{
模板
ostream&operator这肯定是gcc中的一个bug。下面的代码正确地打印了带有叮当声的right
,但带有gcc的error
#include <iostream>
template<typename T> struct A{ T t; };
struct B{};
struct C : public B{};
std::ostream& operator<< (std::ostream& out, const B&)
{ return out << "right"; }
namespace {
template<typename T>
std::ostream& operator<< (std::ostream& out, const A<T>&v)
{ return out << v.t; }
std::ostream& operator<< (std::ostream& out, const C&)
{ return out << "wrong"; }
}
int main(){
A<C> a;
std::cout << a;
}
#包括
模板结构A{T;};
结构B{};
结构C:公共B{};
std::ostream&operator可能与此相关,感谢您指出@T.C。GCC中的运算符查找确实有一些问题。我仍然将其作为一个单独的错误进行归档,因为上下文似乎不同,但根本原因可能相同。我通过切换定义顺序,获得了在GCC上编译的foo
代码。这与您期望的相符吗?这里是。@AustinMullins:是的,符合。这里的要点是,根据标准,带有foo
的示例格式不正确,对于运算符也应该如此
#include <iostream>
template<typename T> struct A{ T t; };
struct B{};
struct C : public B{};
std::ostream& operator<< (std::ostream& out, const B&)
{ return out << "right"; }
namespace {
template<typename T>
std::ostream& operator<< (std::ostream& out, const A<T>&v)
{ return out << v.t; }
std::ostream& operator<< (std::ostream& out, const C&)
{ return out << "wrong"; }
}
int main(){
A<C> a;
std::cout << a;
}