以标准的方式在源代码中指示C++标准

Indicate C++ standard in source in a standard way

本文关键字:标准 指示 C++ 源代码 方式      更新时间:2023-10-16

符合标准的C++编译器定义了一个__cplusplus宏在预处理过程中进行检查,以确定在什么标准下文件正在编译,例如:

#if __cplusplus < 201103L
#error "You need a C++11 compliant compiler."
#endif
#include <iostream>
#include <vector>
int main(){
    std::vector<int> v {1, 2, 3};
    for (auto i : v){
        std::cout << i << " ";
    }
    std::cout << std::endl;
    return 0;
}

我的问题是:

  • 是否有一种标准的方法来指示来源的标准文件是否应该编译

这将允许构建工具在编译之前检查源代码以确定-std=参见shebang的可以指示脚本语言/版本:#!/usr/bin/env python3)。

我能想到的一种非标准且脆弱的方式是寻找预处理器检查__cplusplus,但在上面的例子中,我可以也写过:

#if __cplusplus <= 199711L
#error "You need a C++11 compliant compiler."
#endif

因此,编写(例如正则表达式)要捕获所有变体将变得相当棘手。

编辑:

虽然我很同情@Gary的回答,他建议依赖构建系统,它假设我们实际上将有一个构建步骤。

但你今天已经可以了:

  • 使用解释器运行C++程序,例如使用CINT
  • 或者使用例如rosecompiler的源到源翻译

我的问题也是关于指出源代码是C++以及什么版本它是为(想象一下70年后有人挖出我的代码当C++可能像Cobol今天一样流行时)。

我想我要寻找的等价物是HTML的C++等价物:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

C++标准在某种程度上类似于针对库进行开发。从这个意义上说,库通常以一种在访问新函数的同时慢慢弃用旧函数的方式发展。典型的方法是引入新方法或签名,同时仍然允许访问旧方法或签名。

举个简单的例子,例如,你可以为iPhone制作一个向后兼容IOS4及以上版本的应用程序。您无法选择要支持的特定版本。这很好,因为否则你会将代码进化开放为一个可能性矩阵,使你的代码更难理解和维护。

或者,你可以引入预处理器指令,根据某种版本或标志有条件地构建某些部分。然而,这些都是临时措施,应该随着代码的发展而删除。

因此,我认为,在这种情况下,最好的问题是问问自己,添加这样的东西会真正解决什么问题,会增加不必要的复杂性吗(其中一个代码有糟糕设计的味道)?

在这种情况下,根据经验,我个人认为你最好坚持一个标准。我想你会发现,试图通过散布各种预处理器#ifdef和#ifndefs来区分标准会使理解你的代码库变得难以理解和管理。即使您有一个包含文件,其中定义了允许哪些版本被所有其他文件包含,它也会成为另一个需要管理的文件。。。。更不用说当你更改它时,你必须重新编译包括它在内的所有内容。

如果你担心有人用错误的标准构建你的代码库,那么使用一个不需要开发人员输入这些信息的构建系统。例如Make、Ant、cmake。它使软件的构建变得简单,并清楚地定义了如何以可重复的方式编译项目。如果你走这条路,你会发现试图保护代码不被错误编译是不成问题的。

此外,如果他们使用错误的标准进行编译,他们将遇到大量的编译器错误=)