如何强制g++只编译C++11标准?

10

std::vector<bool>::emplace_back 自 C++14 才可用。然而,使用我的 g++ 5.4.0 编译时,即使我指定 -std=c++11,它也可以编译通过。

当我使用 g++ 4.8.4 编译相同的代码时,它会失败。有没有办法说服 g++ 严格检查所选的标准?

注意:我已经使用了 -pedantic -Wextra -Wall

示例 test.cpp

#include <vector>

int main()
{
    std::vector<bool> v;
    v.emplace_back(true);
    return 0;
}

使用g++ -std=c++11 test.cpp -o test进行编译。在g++ 5.4.0上编译正常,在g++ 4.8.4上会出现错误:

test.cpp: In function ‘int main()’:
test.cpp:6:7: error: ‘class std::vector<bool>’ has no member named ‘emplace_back’
    v.emplace_back(true);
      ^

5
vector<bool>::emplace_back 的缺失并不是符合标准的实现的限制,而是符合标准的程序的限制。实现可以根据需要在标准类中定义其他成员。 - n. m.
有关(同一观察):C++11中的std::vector :: emplace - Sander De Dycker
标准在哪里说实现可以包括额外的成员? - Ayxan Haqverdili
@hyde: 在 OP 编辑后的代码上进行了 演示 - Jarod42
gcc 4.8早于C++14,甚至不支持所有的C++11。难怪它不提供emplace_back()。对于更新的版本,如果您不想使用C++14库功能,请勿编写使用它们的代码。 - Shawn
2
在C++11标准中,脚注188中也提到:实现还可以定义其他成员函数,否则这些函数不会被有效的C++程序调用。 - Daniel Langr
1个回答

8

这与随 gcc 一起发布的 libstdc++ 相关。在 libstdc++bits/vector.tcc 文件中,你会发现对 std::vector<bool> 进行了特化处理。

#if __cplusplus >= 201103L
template<typename _Tp, typename _Alloc>
template<typename... _Args>
// ... more stuff
vector<_Tp, _Alloc>::emplace_back(_Args&&... __args)

预处理器分支使成员函数适用于C++11。在libc++(Llvm项目中的标准库实现)中,情况有所不同:

#if _LIBCPP_STD_VER > 11
template <class... _Args>
#if _LIBCPP_STD_VER > 14
_LIBCPP_INLINE_VISIBILITY reference emplace_back(_Args&&... __args)
#else
_LIBCPP_INLINE_VISIBILITY void      emplace_back(_Args&&... __args)
#endif

因此,在C++11标准之后,emplace_back才被定义。你对此无能为力,但我看到两个选择。

  1. To achieve strict conformance to C++11, not only compile with g++, but also with clang++. clang uses libc++ by default on MacOS, and on Linux you can pass some flag to enforce that (otherwise, it uses libstdc++), which does complain about emplace_back with -std=c++11. Then use the results of compiling with clang to adjust your sources that are otherwise built with gcc.

  2. Compile with gcc, but tell the compiler to use libcxx. From here, this also complains:

    g++ -std=c++11 -nostdinc++ -I /path/to/libcxx/include -nodefaultlibs \
        -lc++ -lc++abi -lm -lc -lgcc vecbool-emplace_back.cpp
    

我会选择选项1,因为它可以使你的程序在多个方面变得更加严谨,而不仅仅是符合标准。此外,选项2过于繁琐。


没有编译器是100%符合标准的。如果你想让你的代码更加健壮,避免出现这样的不可移植行为,你应该使用多个编译器进行构建。 - ComicSansMS
2
Clang并不总是使用libc++,您可能需要请求它(-stdlib=libc++)。默认情况下,它使用libstdc++。 - Marc Glisse
实际上我们使用 g++、MinGW 和 MSVC 进行编译。我们也考虑过使用 clang,但是还没有时间设置自动构建。 - Mi-La
谁负责libstdc++,谁负责libc++?libstdc++是g++的“一部分”吗?那么libc++又是从哪里来的呢? - Mi-La
1
@Mi-La GNU项目用于libstdc++,LLVM项目用于libc++。 - Daniel Langr
是的,libstdc++在某种程度上“是gcc的一部分”,因为它随g++一起发布,并且与此编译器紧密耦合。我认为首席维护者/开发人员是Jonathan Wakely,他也活跃在SO(Stack Overflow)。libc++是Llvm项目的一部分。关于libc++,我想到的人是Marshall Clow和Howard Hinnant(同样都在SO)。但这只是知名个体,当你查看版本控制系统日志时,可能会发现更多涉及的人名。 - lubgr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接