在我自己的命名空间中定义后缀_t数据类型

时间:2016-05-22 00:32:33

标签: c++

POSIX保留了类型的后缀_t,但如果我在自己的命名空间中定义了自己的带有_t后缀的类型怎么办?

3 个答案:

答案 0 :(得分:1)

这就是命名空间发挥作用的原因,就这样做。

最糟糕的是,你定义的类型与posix定义相同,你在命名空间中使用你定义的类型,你也可以用:: posix_type_t引用posix定义。

答案 1 :(得分:1)

我同意user6366161' answer所说的" C对名称空间"一无所知。 POSIX主要是一个C标准,它定义的标题被定义为供C使用(目前C99自POSIX的最后一次主要更新是在2008年,远在C 2011标准发布之前)。因此,当您将一个POSIX标头包含到C ++程序中时,很可能所有引入的名称都在全局命名空间中 - 除非实现已经做了一些意外的事情。

论文

如果将自己的类型名称放在自己的命名空间中,并且在命名空间中对类型和POSIX类型的引用要小心,那么就不会与全局命名空间中的POSIX类型直接冲突。

评论

它有效并不是一个好主意。使用众所周知的POSIX类型故意创建名称冲突是一个坏主意,但该技术可以保护您免受意外冲突(以及与POSIX保留命名空间中未记录的类型的冲突)。

如果尽管有这样做的建议,你决定使用这种技术,你需要小心 - 你会对你的代码的随意读者造成混淆。请注意,当命名空间中的代码使用没有任何范围限定符的类型时,它会在非限定名称冲突时使用您的类型而不是POSIX类型。您可以使用全局范围运算符来获取与命名空间中的POSIX类型名称冲突的POSIX类型名称。

说明性代码

这是一个例子。计算毫无意义 - 目标是使用pid_t类型(来自POSIX的整数类型)和另一种类型pid_t来处理单独的命名空间(NonPosix )并且是long double的别名。

#include <cmath>
#include <unistd.h>

namespace NonPosix
{
    typedef long double pid_t;
    pid_t gruesome(pid_t pos);
    void unsightly();
}

#include <iostream>

using NonPosix::gruesome;
namespace { void obnoxious(); }

int main()
{
    pid_t pid = getpid();
    NonPosix::pid_t angle = gruesome(2.0304815L);

    std::cout << "PID = " << pid << "; angle = " << angle << "\n";

    obnoxious();
    NonPosix::unsightly();

    return 0;
}

// The using statement is invalid - pid_t is already defined in the global scope
#ifdef TRY_USING_NONPOSIX_PID_T
using NonPosix::pid_t;
#endif

namespace {

void obnoxious()
{
    pid_t pid = getppid() + 0.71;   // This is an integral type!
    std::cout << "Obnoxious:\n";
    std::cout << "PID = " << pid << "; angle = " << gruesome(pid) << "\n";
}

}

namespace NonPosix
{

pid_t gruesome(pid_t pos)
{
    pid_t apos = pos + 2.22;
    pid_t rval = atan2l(pos, apos);
    std::cout << "Gruesome: POS = " << pos << "; APOS = " << apos
              << "; RVAL = " << rval << "\n";
    return rval;
}

void unsightly()
{
    pid_t pid = getpid() + 0.65;
    std::cout << "Unsightly:\n";
    std::cout << "PID = " << pid << "; angle = " << gruesome(pid);
    ::pid_t ppid = getppid() + 0.29;    // This is an integral type
    std::cout << "; PPID = " << ppid << "\n";
}

}

代码是演示代码,而不是生产代码,但我认为它说明了一些观点。

示例输出

Gruesome: POS = 2.03048; APOS = 4.25048; RVAL = 0.445654
PID = 7765; angle = 0.445654
Obnoxious:
Gruesome: POS = 670; APOS = 672.22; RVAL = 0.783744
PID = 670; angle = 0.783744
Unsightly:
Gruesome: POS = 7765.65; APOS = 7767.87; RVAL = 0.785255
PID = 7765.65; angle = 0.785255; PPID = 670

最值得注意的是,它说明了我的基本论点:

  • 在用户定义的名称空间中使用_t后缀定义的类型不会与POSIX类型直接冲突,因为POSIX类型位于全局名称空间中。
  • 当名称与基本POSIX类型(如pid_t)冲突时,使用此类型不是一个好主意。

答案 2 :(得分:0)

C对名称空间一无所知。如果包含POSIX头文件,它将使用其类型污染全局名称空间。将您自己的类型放入命名空间不会解决任何问题。