在命名空间中使用来自全局命名空间的函数
Using functions from global namespace in a namespace
我正在使用命名空间下的库,我们称它为 Hello。
namespace Hello {
template<class T>
void World(std::ostream& os, const T& t) {
os << t;
}
}
class T
有点像std::array<int,10>
,我还为它写了一个ostream重载函数。但是,调用 Hello::World(arr)
会导致编译错误,即编译器找不到 operator<<()
.
的重载
经过一番搜索,我想出了一个解决方案来解释这种情况。
How does the operator overload resolution work within namespaces? and Name resolution of functions inside templates instantiated with qualified types.
所以我们可以像这样简化情况。
void f(int) {}
void f(int,int) {}
namespace Hello {
using ::f;
void f(int,int,int) {}
void World()
{
f(100);
f(100, 200);
f(100, 200, 300);
}
};
int main()
{
Hello::World();
return 0;
}
没有 using ::f;
行,此代码无法编译,因为名称 f
可以隐藏 所有具有相同名称的函数 全局命名空间。
现在这是我的问题:
- 既然
namespace Hello { .... }
在库里,就不修改了。也就是我不能修改World()
里面的实现。唯一的解决办法是在我的代码中的某个地方放一行 namespace Hello { using ::f; }
。这是一个很好的做法,还是有更优雅的解决方案?
- 在这个例子中,我可以只导入
f(int)
而不是 f(int,int)
吗?
Is it a good practice, or there is a more elegant solution?
恕我直言,您可以将其与第三方库一起使用。它足够清晰和表达。如果能这样写就更好了:
void World() {
::f(100); // f from global namespace
::f(100, 200); // f from global namespace
f(100, 200, 300); // f NOT from global namespace
}
因为这样就可以清楚地看到全局名称空间中哪个函数 是 哪个 不是 但此解决方案对您不起作用因为您不能修改 World
函数的实现。
Can I only import f(int)
and not f(int, int)
?
是的。您可以执行以下操作以仅导入 f(int)
函数:
void f(int) {}
namespace Hello {
using ::f; // only void f(int) is defined before this line
// therefore, it is the only overload being imported to the Hello namespace
}
void f(int,int) {}
更新
如果您只想导入 operator<<
的一个重载,而不是普通函数,那么您可以将每个重载包装在一个单独的命名空间中,如下所示:
namespace XX {
struct X {
int x;
};
std::ostream& operator<<(std::ostream& os, X const& x) {
return os;
}
}
namespace YY {
std::ostream& operator<<(std::ostream& os, Y const& y) {
return os;
}
struct Y {
double y;
};
}
namespace Hello {
using ::XX::X;
using ::XX::operator<<;
using ::YY::Y;
}
看看live.
我正在使用命名空间下的库,我们称它为 Hello。
namespace Hello {
template<class T>
void World(std::ostream& os, const T& t) {
os << t;
}
}
class T
有点像std::array<int,10>
,我还为它写了一个ostream重载函数。但是,调用 Hello::World(arr)
会导致编译错误,即编译器找不到 operator<<()
.
经过一番搜索,我想出了一个解决方案来解释这种情况。 How does the operator overload resolution work within namespaces? and Name resolution of functions inside templates instantiated with qualified types.
所以我们可以像这样简化情况。
void f(int) {}
void f(int,int) {}
namespace Hello {
using ::f;
void f(int,int,int) {}
void World()
{
f(100);
f(100, 200);
f(100, 200, 300);
}
};
int main()
{
Hello::World();
return 0;
}
没有 using ::f;
行,此代码无法编译,因为名称 f
可以隐藏 所有具有相同名称的函数 全局命名空间。
现在这是我的问题:
- 既然
namespace Hello { .... }
在库里,就不修改了。也就是我不能修改World()
里面的实现。唯一的解决办法是在我的代码中的某个地方放一行namespace Hello { using ::f; }
。这是一个很好的做法,还是有更优雅的解决方案? - 在这个例子中,我可以只导入
f(int)
而不是f(int,int)
吗?
Is it a good practice, or there is a more elegant solution?
恕我直言,您可以将其与第三方库一起使用。它足够清晰和表达。如果能这样写就更好了:
void World() {
::f(100); // f from global namespace
::f(100, 200); // f from global namespace
f(100, 200, 300); // f NOT from global namespace
}
因为这样就可以清楚地看到全局名称空间中哪个函数 是 哪个 不是 但此解决方案对您不起作用因为您不能修改 World
函数的实现。
Can I only import
f(int)
and notf(int, int)
?
是的。您可以执行以下操作以仅导入 f(int)
函数:
void f(int) {}
namespace Hello {
using ::f; // only void f(int) is defined before this line
// therefore, it is the only overload being imported to the Hello namespace
}
void f(int,int) {}
更新
如果您只想导入 operator<<
的一个重载,而不是普通函数,那么您可以将每个重载包装在一个单独的命名空间中,如下所示:
namespace XX {
struct X {
int x;
};
std::ostream& operator<<(std::ostream& os, X const& x) {
return os;
}
}
namespace YY {
std::ostream& operator<<(std::ostream& os, Y const& y) {
return os;
}
struct Y {
double y;
};
}
namespace Hello {
using ::XX::X;
using ::XX::operator<<;
using ::YY::Y;
}
看看live.