[英]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;
}
歧義似乎意味着,一般來說,如果一個類從命名空間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
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.