是否可以将函数导入名称空间,但不能导出呢?

时间:2018-10-23 23:06:55

标签: c++

是否可以将函数(或其他符号)导入命名空间但不能导出?例如,我想将std::string导入当前名称空间,但我不希望current::string可见。

namespace current {
  using std::string;
  string func();
}

current::string应该不是问题。

用例只是减少输入(并经常忘记使用std::string等),并使代码更易读,而不会导致所有名称空间语法混乱。

4 个答案:

答案 0 :(得分:5)

  

是否可以将函数(或其他符号)导入命名空间但不能导出?

不。

using指令将引入所有引用您在声明中使用的名称的符号,并且current的用户将看到它们,就像它们实际上是在名称空间本身中声明的一样。

该标准的相关部分在[namespace.udir]/1中:

  

using伪指令指定可以在使用伪指令之后出现using伪指令的范围内使用指定命名空间中的名称。在进行非限定名称查找(6.4.1)期间,这些名称看起来好像是在包含使用指令和指定名称空间的最近的封闭名称空间中声明的一样。 [注意:在本文中,“包含”是指“直接或间接包含”。 —尾注]

答案 1 :(得分:2)

“计算机科学中的所有问题都可以通过另一种间接解决方案来解决” – David Wheeler

在这种情况下,绝对是这样:

namespace current {
    namespace impl {
        using std::string;
        string func();
    }

    using impl::func;
}

诚然,有费用:

  • 鉴于在C ++中无法从中排除单个符号,因此它迫使您列出要从current导出的每个单个类型或函数。 using namespace。 (只需将其视为一项功能,因为它可以使您的API的内容刻意而不是巧合。)
  • 如果您需要保持与ABI兼容,这将无法正常工作(func的名称会在我所知道的所有实现中更改)

顺便说一句,名称空间名称current表明您可能还考虑了版本控制。这两种方法可以很好地结合起来,例如:

namespace _v1 {
    namespace impl {
        int func();
    }

    // Exports
    using impl::func;
}
namespace _v2 {
    namespace impl {
        using std::string;
        string func();
    }

    // Exports
    using impl::func;
}

namespace current = _v2;

答案 2 :(得分:0)

如果不导出函数的返回值,则不能导出函数func

问题应该是,func在给定名称空间中有意义的名称是什么。如果current::string没有意义,那么string可能是func结果的坏名字吗?它返回什么?例如一些代码? current::code更好吗?然后在string中将code重命名为current

namespace current {
    using code = std::string;
    code func();
}

尝试尽可能减少打字不是一个好主意。否则,最好的办法是尽可能使用短名称:

namespace c {
    using s = std::string;
    s f();
}

这将使它的使用非常隐秘。

答案 3 :(得分:-1)

否,您的代码是错误的做法。尽管您的特定示例std::string可能不会引起冲突,但未命名的查找可能会将对其他string的定义的引用拉到命名空间范围的之外,从而可能导致重新声明错误或使用与您期望的名称不同的名称进行未命名的查找。例如,可能会发生这种情况:a)您或您代码中的其他人使用的名称与库冲突(例如distance),b)库使用的名称冲突(例如Boost),c)或其他翻译单元从外部作用域引入了不同的名称,从而导致相似的代码具有完全不同的行为。

要么始终完全限定您的声明,要么至少使用using ::std::string