【问题标题】:Why does the C struct hack not work for C++ template declarations?为什么 C struct hack 不适用于 C++ 模板声明?
【发布时间】:2020-08-23 07:23:59
【问题描述】:

C 有一个有趣的技巧,一个名字可以用来声明一个类型和一个函数:

struct foo {};
void foo(void);

现在,每当我写 foo 时,编译器都会假定我指的是函数,除非我在它前面加上 struct

foo();  // call void foo(void)
struct foo bar;  // declare variable of type struct foo

即使使用命名空间和嵌套,这在 C++ 中也很有效! 但它不适用于模板:

template <typename> void bar(void);
template <typename> struct bar {};
// error: conflicting declaration of template struct bar
// previous declaration: template void bar()

为什么?

我们已经开始处理依赖上下文中的消歧器了:

typename foo<A>::b();
foo<A>::template b<C>();

将常规规则应用于此类模棱两可的模板名称似乎并不难。

假设同名对我很重要。我能以某种方式完成这项工作吗?

【问题讨论】:

  • 如果您正在寻找 C++ 标准中的“章节和诗句”,您可能需要添加 language-lawyer 标签,并且可能需要交叉引用 C 标准中的细微差别、差异和相似之处。
  • 好建议。完成。
  • 因为它是 struct hack,而不是 template hack。

标签: c++ templates struct language-lawyer name-lookup


【解决方案1】:

为什么?

答案在问题的正文中。这适用于类和函数,因为在 C 中,结构标记和函数标识符有一个单独的命名空间。如果 C++ 旨在与 C 代码互操作,则它必须保留此行为。只需要查看像stat function 这样的API 采用struct stat 参数即可了解为什么C++ 保留了此类代码的有效性。这种使用命名空间的方法只是与驻留在全局命名空间中的 C 代码内联(因此 ::statstruct ::stat 应该在需要时继续工作)。

然而,在 C++ 中,类标签的标识符与常规标识符共享一个“命名空间”。因此,这种“hack”的有效性是通过 C++ 规范中的一种特殊情况来实现的,即在类发生冲突时简单地隐藏类。

[basic.scope.hiding]

2一个类名或者枚举名可以被一个名字隐藏 变量、数据成员、函数或枚举器在同一文件中声明 范围。如果一个类或枚举名称和一个变量、数据成员、 函数或枚举器在同一范围内声明(以任何顺序) 具有相同的名称,类或枚举名称隐藏在任何地方 变量、数据成员、函数或枚举器名称是可见的。

C++ 的设计者认为这是一个好主意还是坏主意并不重要。为了便于与某些系统进行互操作,C++ 编译器应继续接受遗留代码作为有效代码。

但是没有处理需要相同行为的模板的遗留代码。模板完全是 C++ 构造(与 C 完全无关)。因此,语言设计也没有外部约束来为模板名称添加更多特殊情况。所以它没有。

假设同名对我很重要。我能以某种方式完成这项工作吗?

没有办法让它工作。

【讨论】:

    【解决方案2】:

    措辞在temp.pre-7:

    类模板不得与同一范围内的任何其他模板、类、函数、变量、枚举、枚举器、命名空间或类型具有相同的名称([basic.scope]),除非 [temp.class.spec] 中指定...

    temp.class.spec 中的所有点都与此示例不冲突。

    因此,就目前而言,类模板和函数模板不能使用相同的名称。

    【讨论】:

    • 委员会是否考虑取消此限制作为实施 CTAD 的一种方式?
    • 我不确定你的意思;我们已经有了 CTAD。另外,我不认为这是一种限制,而是一种功能。理想情况下,即使是非模板,我也不希望这样做。
    • 我们今天有 CTAD,但在 14 到 17 之间这是一个悬而未决的问题。 std::pair a(1, 2); 是否比 auto a = std::pair(1, 2); 好得多,后者使用的功能类似于 std::make_pair
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多