在命名空间中使用来自全局命名空间的函数

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 可以隐藏 所有具有相同名称的函数 全局命名空间。

现在这是我的问题:

  1. 既然namespace Hello { .... }在库里,就不修改了。也就是我不能修改World()里面的实现。唯一的解决办法是在我的代码中的某个地方放一行 namespace Hello { using ::f; } 。这是一个很好的做法,还是有更优雅的解决方案?
  2. 在这个例子中,我可以只导入 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) {}

Demo

更新

如果您只想导入 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.