命名空间内的友元函数声明/定义
Friend function declaration/definition inside a namespace
考虑一个名称空间中的类。类的定义声明了一个友元函数。
namespace Foo
{
class Bar
{
friend void baz();
};
}
根据我所知道的,这应该将baz()
声明为最内层封闭命名空间的成员,即Foo
。
因此,我期望baz()
的以下定义是正确的:
void Foo::baz() { }
但是,GCC(4.7)给了我一个错误。
error: ‘void Foo::baz()’ should have been declared inside ‘Foo’
有几个解决方案似乎有效:
在类外声明
baz()
。namespace Foo { void baz(); class Bar { friend void baz(); }; }
在命名空间内定义
baz()
namespace Foo { class Bar { friend void baz(); }; } ... namespace Foo { void baz() { } }
使用
-ffriend-injection
标志编译,可以消除错误
这些解决方案似乎与我所知道的c++中声明/定义的一般规则不一致。
为什么我必须声明baz()
两次?
为什么定义只在名称空间中合法,而在作用域解析操作符中不合法?
为什么这个标志消除了错误?
为什么我必须声明baz()两次?
因为友元声明没有在命名空间中提供可用的函数声明。它声明,如果该函数在该命名空间中声明,它将是友元;如果要在类中定义友元函数,则可以通过依赖参数的查找(而不是其他方式)获得它,就像在命名空间中声明一样。
为什么定义只在名称空间中合法,而在作用域解析操作符中不合法?
因为它没有(正确地)在名称空间中声明,并且如果函数已经声明,则只能在其名称空间之外定义(具有作用域解析)。
为什么这个标志消除了错误?
因为该标志使友元声明充当命名空间中的声明。这是为了与c++的古代方言(显然,还有一些现代编译器)兼容,在这些方言中,这是标准行为。
第一段代码应该这样编译:
namespace A {
struct B {
friend void foo();
};
}
void A::foo() {}
尽管该特定函数不能使用,除非您还在命名空间级别提供声明。原因是友元声明只能通过参数依赖查找(ADL)看到,但foo
不依赖于A::B
,因此编译器永远不会查看该类型的内部。
相关文章:
- 如何在C++中声明/定义相互依赖的模板?
- C++概念是否允许我的类在声明/定义中指定它满足某些概念?
- MSVC:无法识别的模板声明/定义(使用 Clang/GCC 编译)
- 我可以重用同一个模板来声明/定义多个东西吗(而不复制模板代码)
- C++-模板类中模板函数的单独声明/定义
- 在C 中使用继承时,请避免使用未缴纳的函数声明/定义
- C++模板能否确定所声明/定义的实例是否为常量
- 如何在程序中声明/定义一次并在两个类中使用映射列表
- LBNF,C函数声明/定义,减少冲突
- 声明/定义返回具有自动返回类型的 valarray 的函数时的隔离错误
- #用{}和声明定义混淆
- CTOR 声明/定义中接受的 const 限定符(LLVM 错误?)
- C++ 从一个源文件中声明/定义的变量从另一个源文件访问另一个源文件
- 无法识别的模板声明/定义
- 只在.cpp中声明/定义静态方法可以吗
- 声明/定义自定义类定制对象的正确方法
- typedef声明定义未命名类时链接失败
- 用visual c++实现COM对象的声明/定义和实例化
- VS 2012中的显式模板声明/定义
- 命名空间内的友元函数声明/定义