【问题标题】:Is using explicit return type in one translation unit and deduced return type in another allowed?是否允许在一个翻译单元中使用显式返回类型并在另一个翻译单元中使用推导返回类型?
【发布时间】:2021-03-04 17:47:11
【问题描述】:

我的问题类似于this one,但略有不同。

假设我有两个翻译单元exec.cpplib.cpp,如下:

// exec.cpp

int foo();

int main() {
    return foo();
}

// lib.cpp

auto foo() {
    return 42;
}

将它们编译并链接在一起是否合法?还是不正确的 NDR?

注意:g++ 和 clang 都使用命令 <compiler> exec.cpp lib.cpp -o program 生成预期的可执行文件(即返回 42)

注意:可以说这是一种不好的做法(因为如果实现发生变化,返回类型可能会改变,并破坏代码)。但我还是想知道答案。

【问题讨论】:

  • 即使它不是非法的,从长远来看也会导致难以调试的微妙问题,从而从长远来看会浪费您的时间。为什么要冒险。
  • 不要在 cmets 中回答,人们
  • @LanguageLawyer 不是这样。只有一个定义。
  • 但是在另一个翻译单元中的 delcaring 是否包含“重新声明”? 不是你的情况,至少根据the current wording
  • 我希望eel.is/c++draft/basic.link#11 成为这里的控制规则,但我认为在这种情况下如何解释“相同类型”并不是特别清楚。

标签: c++ c++14 language-lawyer auto


【解决方案1】:

以下所有标准参考均指N4861: March 2020 post-Prague working draft/C++20 DIS.


来自[basic.link]/11 [强调我的]:

所有类型调整后(在此期间 typedef 被其定义替换),所有引用给定变量或函数的声明所指定的类型应是相同的,除了数组对象的声明可以指定数组类型,这些数组类型因存在或不存在主要数组绑定([dcl.array])而不同。在类型标识上违反此规则不需要诊断。

[dcl.spec.auto]/3 涵盖了占位符类型可以与函数声明符一起出现,并且如果此声明符不包含 trailing-return-type(就像 OP 的示例一样)

[...] 否则 [no trailing-return-type],函数声明器应声明一个函数

在哪里

[...] 函数的返回类型是从函数体 ([stmt.if]) 中未丢弃的 return 语句(如果有)推导出来的。

[dcl.fct]/1 涵盖了不包含 trailing-return-type [emphasis 的函数声明符,删除了语法的 opt 部分不适用于此特定示例]:

在声明 T D 中,D 的形式为 [...] Ddeclarator-id 的类型是derived-declarator-type-list 函数的 parameter-type-list 返回 T” [...]

因此,两个声明

int f();      // #1
auto foo() {  // #2
    // [dcl.spec.auto]/3:
    // return type deduced to 'int'
}

两者都声明了这些T D 声明中D 中相关declarator-id 类型的函数

derived-declarator-type-list 函数的 parameter-type-list 返回 T

在这两种情况下,Tint

  • #1中明确指定,
  • 根据 #2 中的 [dcl.spec.auto]/3 推断。

因此,声明#1#2,经过所有类型的调整,具有相同的(函数)类型,从而满足[basic.link]/11,并且OP的示例格式正确。但是,auto f() 定义的任何细微变化都可能导致推导出的返回类型不是 int,在这种情况下违反 [basic.link]/11,NDR。

【讨论】:

    猜你喜欢
    • 2015-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-02
    • 1970-01-01
    • 2021-02-24
    相关资源
    最近更新 更多