在除 ADL、“本地”或全局命名空间之外的命名空间中定义函数
Posted
技术标签:
【中文标题】在除 ADL、“本地”或全局命名空间之外的命名空间中定义函数【英文标题】:Defining a function in a namespace other than the ADL, "local" or global namespace 【发布时间】:2016-04-04 11:44:22 【问题描述】:请看下面的代码:
#include <iostream>
/// Definition of void perform(a_lib::a_class&). Where should I put this definition?
/// See the comments below for where I've tried placing it.
// void perform(a_lib::a_class&)
// std::cout << "performing on a_lib::a_class" << std::endl;
//
namespace a_lib
class a_class ;
// WORKS HERE but it pollutes a_lib (namespace of third-party library).
namespace mine
// DOESN'T WORK HERE: "use of undeclared identifier 'perform'".
// WORKS HERE but it pollutes the global namespace.
namespace b_lib
// WORKS HERE but it pollutes b_lib (namespace of third-party library).
template <typename Type>
void b_func(Type& obj)
perform(obj);
namespace mine
// DOESN'T WORK HERE: "use of undeclared identifier 'perform'".
void run()
a_lib::a_class a_obj;
b_lib::b_func(a_obj);
int main(int, char**)
mine::run();
return 0;
a_lib
和 b_lib
是属于两个不同第三方库的命名空间。 mine
是我自己的命名空间。
我被告知污染全局命名空间是个坏主意,在this question 中,他们还说向std
添加类型是个坏主意。我认为后者通常适用于名称空间。您不应该将类型添加到不属于您的命名空间。
但是我如何在不违反这些原则的情况下解决上述问题呢?我应该把perform()
的定义放在哪里,如何让b_func()
调用它?
上下文:我正在尝试在我自己的命名空间中为 SFML 类型添加外部 cereal serialize()。这是一个简化的例子。
【问题讨论】:
要扩展a_lib::a_class
的接口,您应该将内容添加到该类型的命名空间。扩展您不拥有的类型的接口是否是一个好主意(例如,通过使它们可序列化)是关键问题,但如果您要这样做,那么您应该在类型的命名空间中进行。另一种选择是在您自己的命名空间中定义您自己的派生自a_class
的类型,并在您的命名空间中添加序列化支持。
“扩展你不拥有的类型的接口是否是一个好主意(例如,通过使它们可序列化)是关键问题” 这是一个非常好的观点。我将从a_class
派生。谢谢。
【参考方案1】:
你需要确定编译器在哪里,在处理“b_func”的时候可以找到“perform”。
namespace mine
// DOESN'T WORK HERE: "use of undeclared identifier 'perform'".
// dom - yes it will, but there is 'more' to the name than your example shows
void perform(Type& obj) /* do something with obj */
// WORKS HERE but it pollutes the global namespace.
namespace b_lib
// WORKS HERE but it pollutes b_lib (namespace of third-party library).
// dom - use here is easy with correct and 'more-complete' name:
template <typename Type>
void b_func(Type& obj) mine::perform(obj);
// -----------------------^^^^^^^^^^^^^^^^^^^ --- more to name
由于“我的”是一个名称空间,一个更完整的名称可以“跨越”名称空间。
请注意,在我的::perform() 实现中,还必须定义“类型”才能使用 obj。
【讨论】:
如果我理解正确,您是在建议我编辑b_func()
的定义。问题是它是第三方库的一部分,因此我不应该编辑它的定义。
如果不能修改 b_func,那么 b_func() 当前必须调用已经存在的“perform()”方法/函数。顾名思义,“性能”已经在全球范围内,因此不能增加更多的“污染”。
不,它不建议这样做。大概它调用了不合格的函数,以便 ADL 找到它,以便找到在a_lib::a_class
的关联命名空间中定义的函数。
对不起,我没听说过ADL,找不到。以上是关于在除 ADL、“本地”或全局命名空间之外的命名空间中定义函数的主要内容,如果未能解决你的问题,请参考以下文章