C ++ 20是否要求将源代码存储在文件中?

JVA*_*pen 103 c++ language-lawyer c++20 std-source-location

但是,一个有点奇怪的问题是,如果我没有记错的话,C ++源代码不需要文件系统来存储其文件。

拥有一个可以通过照相机扫描手写纸的编译器将是一个符合要求的实现。尽管实际上没有太大意义。

但是,C ++ 20现在使用添加了源位置file_name。现在,这是否意味着源代码应始终存储在文件中?

ein*_*ica 104

不,源代码不必来自文件。

您可以在管道中完全编译(和链接)C ++,将编译器置于中间,例如

generate_source | g++ -o- -xc++ - | do_something_with_the_binary
Run Code Online (Sandbox Code Playgroud)

几十年来一直如此。也可以看看:

std::source_locationC ++ 20中的引入不会改变这种状况。只是某些代码没有明确定义的源位置(或者可能定义明确,但意义不大)。其实,我想说的是定义上的坚持std::source_location使用的文件是有点近视......虽然在公平,它只是一个宏观相当于少的__FILE____LINE__这已经存在C ++(和C)。

@ HBv6指出,如果您__FILE__在标准输入流中使用GCC进行编译时打印的值:

echo -e '#include <iostream>\n int main(){std::cout << __FILE__ ;}' | g++ -xc++  -
Run Code Online (Sandbox Code Playgroud)

运行生成的可执行文件<stdin>

源代码甚至可以来自Internet。

@Morwenn注意到此代码:

#include <https://raw.githubusercontent.com/Morwenn/poplar-heap/master/poplar.h>

// Type your code here, or load an example.
void poplar_sort(int* data, size_t size) {
    poplar::make_heap(data, data + size);
    poplar::sort_heap(data, data + size);
}
Run Code Online (Sandbox Code Playgroud)

可以在GodBolt上运行(但不能在您的计算机上运行-没有流行的编译器支持此功能。)

您是语言律师吗?好的,让我们参考该标准。

语言标准中并未明确回答C ++程序源是否需要来自文件的问题。查看C ++ 17标准(n4713)的草稿,第5.1节[lex.separate]如下:

  1. 该程序的文本在本文档中以称为源文件的单元形式保存。通过预处理指令#include将源文件以及所有标头(20.5.1.2)和包含的源文件(19.2)以及任何有条件包含(19.1)预处理指令跳过的任何源行,称为翻译单元。

因此,源代码本身不一定保存在文件中,而是保存在“称为源文件的单元”中。但是,包含项从何而来?有人会假设它们来自文件系统上的命名文件...但是也不是强制性的。

无论如何,std::source_location似乎并没有改变C ++ 20中的措辞或影响其解释(AFAICT)。

  • 刚刚在GCC上尝试过:“ echo'#include &lt;stdio.h&gt; \ nint main(){printf(“%s \\ n”,\ _ \ _ FILE \ _ \ __); return 1;}'| gcc- o测试-xc-”(不带引号)。执行后,将输出&lt;stdin&gt;。 (13认同)
  • 关于标准(和科学)中的术语,名称和概念,这是一件有趣的事情:它们通常是原子的。也就是说,“源文件”不一定是“源”的“文件”,实际上,术语“文件”可能根本就没有定义-与数学中的数字相比:没有“数字”,“自然数字”,“理性数字”,“实数”等。 (10认同)
  • 就标准而言,该管道是“源文件”。 (8认同)
  • @melpomene:这些单位只是被称为源文件,并没有说它们实际上必须是源文件。但我将编辑答案以包括此内容。 (8认同)
  • 我正在查看C标准,该标准定义为:“程序的文本在此国际标准中以称为*源文件*(或*预处理文件*)的单元形式保存。” 因此,无论代码存储在哪里,它都是Standardese中的“源文件”。(附录:在[lex]下的C ++标准中可以找到类似的语言。) (5认同)
  • 我看不出它是什么“奖励功能”。这是标准功能的合规结果。 (5认同)
  • @Barmar:答案似乎是“是的,我们是。” 但是,嘿-不要开枪,我没有写标准:-) (3认同)
  • @bolov:这比我说的还要激怒……而且,对此答案的评论也不适合进行此讨论。我也至少部分不同意您的主张。 (2认同)

eer*_*ika 51

甚至在C ++ 20之前,该标准就具有:

__FILE__
Run Code Online (Sandbox Code Playgroud)

当前源文件的假定名称(字符串文字)。

的定义与相同source_location::file_name

因此,在C ++ 20中对无文件系统实现的支持方面没有变化。

该标准并未确切定义“源文件”的含义,因此是否引用文件系统可能取决于解释。如果确实可以识别该语言的实现中的“源文件”,则可能是实现可以生成“您刚刚给我的手写便笺”。


结论:是的,标准将源称为“文件”,但是未指定“文件”是什么以及是否涉及文件系统。

  • 我只能看到`scanner-c ++`返回*“左柜子,第三个抽屉,第四个红色标签的文件夹,第17页” *。 (4认同)
  • @Yksisarvinen:委员会通常会为那些晦涩的实施可能有充分理由做一些与平常行为相反的事情的情况留出余地。这样,它依赖于编译器作者来判断他们的客户是否会发现普通行为比其他选择有用或更少。此类事情留给实施者判断的事实可能被视为“模棱两可”,但这是有意的,因为优秀的编译器作者将比委员会更了解其客户的需求。 (3认同)
  • @Yksisarvinen我不完全了解规则“推定”限定的意图,但我*假定* :)是为了澄清文件名不需要是绝对的或规范的,而是来自的相对名称编译器的角度就足够了。我可能是错的。 (2认同)
  • FWIW,在POSIX意义上,管道(或任何其他类似文件的事物)是“文件”,因此,在这种意义上,stdin / stdout是“文件”,而不是磁盘文件等。 (2认同)
  • @dmckee ... *在一个废弃的厕所里,门上有一个牌子,上面写着“当心豹子。”* (2认同)