将单个 class 导入命名空间似乎要求命名空间之间没有函数名称冲突
Importing a single class into a namespace appears to require that there be no function name collisions between the namespaces
由于在使用 bar::Rectangle
实例化 bar::BuildStream
时对 BuildStream
的模糊调用,以下代码(令人惊讶?)无法使用 g++
或 clang++
进行编译] 作为输入。
#include <iostream>
#include <sstream>
namespace foo {
struct Rectangle { double height, width; };
std::ostream& operator<<(std::ostream& os, const Rectangle& a) { return os; }
inline void BuildStream(std::ostringstream& os) { }
template<typename T, typename... Args>
void BuildStream
(std::ostringstream& os, const T& item, const Args& ...args) {
os << item;
BuildStream(os, args...);
}
} // namespace foo
namespace bar {
inline void BuildStream(std::ostringstream& os) { }
template<typename T, typename... Args>
void BuildStream
(std::ostringstream& os, const T& item, const Args& ...args) {
os << item;
BuildStream(os, args...);
}
using Rectangle = foo::Rectangle;
} // namespace bar
int main(int argc, char* argv[]) {
std::ostringstream os;
bar::BuildStream(os, 1, 2);
bar::BuildStream(os, bar::Rectangle(), bar::Rectangle());
return 0;
}
歧义似乎意味着,一般来说,如果将 class 从命名空间 foo
导入命名空间 bar
,则必须注意确保没有函数bar
中的名称等同于 foo
中的函数。这显然破坏了命名空间的一些好处;是否有更微妙的方法来避免这种歧义?
上下文是 foo
是一个大型库的命名空间,bar
是一个消费者项目的命名空间(这个问题在实践中出现了)。
这里的问题与参数相关的查找有关。 bar::Rectangle
实际上是一个 foo::Rectangle
,因此对 BuildStream(os,args...)
的调用需要检查 foo's
命名空间以及重载。
确实需要小心。您可以通过限定调用来避免歧义:
template<typename T, typename... Args>
void BuildStream(std::ostringstream& os, const T& item, const Args& ...args)
{
os << item;
bar::BuildStream(os, args...); // qualified
}
由于在使用 bar::Rectangle
实例化 bar::BuildStream
时对 BuildStream
的模糊调用,以下代码(令人惊讶?)无法使用 g++
或 clang++
进行编译] 作为输入。
#include <iostream>
#include <sstream>
namespace foo {
struct Rectangle { double height, width; };
std::ostream& operator<<(std::ostream& os, const Rectangle& a) { return os; }
inline void BuildStream(std::ostringstream& os) { }
template<typename T, typename... Args>
void BuildStream
(std::ostringstream& os, const T& item, const Args& ...args) {
os << item;
BuildStream(os, args...);
}
} // namespace foo
namespace bar {
inline void BuildStream(std::ostringstream& os) { }
template<typename T, typename... Args>
void BuildStream
(std::ostringstream& os, const T& item, const Args& ...args) {
os << item;
BuildStream(os, args...);
}
using Rectangle = foo::Rectangle;
} // namespace bar
int main(int argc, char* argv[]) {
std::ostringstream os;
bar::BuildStream(os, 1, 2);
bar::BuildStream(os, bar::Rectangle(), bar::Rectangle());
return 0;
}
歧义似乎意味着,一般来说,如果将 class 从命名空间 foo
导入命名空间 bar
,则必须注意确保没有函数bar
中的名称等同于 foo
中的函数。这显然破坏了命名空间的一些好处;是否有更微妙的方法来避免这种歧义?
上下文是 foo
是一个大型库的命名空间,bar
是一个消费者项目的命名空间(这个问题在实践中出现了)。
这里的问题与参数相关的查找有关。 bar::Rectangle
实际上是一个 foo::Rectangle
,因此对 BuildStream(os,args...)
的调用需要检查 foo's
命名空间以及重载。
确实需要小心。您可以通过限定调用来避免歧义:
template<typename T, typename... Args>
void BuildStream(std::ostringstream& os, const T& item, const Args& ...args)
{
os << item;
bar::BuildStream(os, args...); // qualified
}