从bug 80985开始考虑这个例子:
template <class Func>
void call(Func f)
{
f();
}
void func() noexcept { }
int main()
{
call(func);
}
Run Code Online (Sandbox Code Playgroud)
正如您所做的那样,在启用所有警告的情况下进行编译会产生:
$ g++ -std=c++14 -Wall foo.cxx
foo.cxx:2:6: warning: mangled name for ‘void call(Func) [with Func = void (*)() noexcept]’ will change in C++17 because the exception specification is part of a function type [-Wnoexcept-type]
void call(Func f)
^~~~
Run Code Online (Sandbox Code Playgroud)
我应该怎么做这个警告呢?修复是什么?
在编写一些针对C++ 17的代码时,我遇到了一个障碍,它决定了合并两个兼容的std :: unordered_maps的操作的异常安全性.根据目前的工作草案 §26.2.7,表91部分内容涉及以下条件a.merge( a2 ):
要求:
a.get_allocator() == a2.get_allocator().尝试提取每个元素
a2并a使用哈希函数和密钥相等谓词将其插入a.在具有唯一键的容器中,如果键中的元素a与元素的键相等a2,则不会从中提取该元素a2.后置条件:指针和对转移元素的
a2引用引用那些相同的元素但作为成员a.引用传递元素的迭代器和引用的所有迭代器a都将失效,但剩余元素的迭代器a2将保持有效.抛出:除非散列函数或键等式谓词抛出,否则无效.
值得注意的是,这些条件强烈地让人联想到普通关联容器(std :: map)的要求,如§26.2.6,表90所示a.merge( a2 ):
要求:
a.get_allocator() == a2.get_allocator().尝试提取每个元素
a2并a使用比较对象将其插入a.在具有唯一键的容器中,如果键中的元素a与元素的键相等a2,则不会从中提取该元素a2.后置条件:指针和对转移元素的
a2引用引用那些相同的元素但作为成员a.引用传递元素的迭代器将继续引用它们的元素,但它们现在表现为迭代器a,而不是a2.抛出:除非比较对象抛出,否则无效.
我需要合并两个std :: unordered_maps和相同数量的元素,我可以确保这两个元素在两个容器中都是唯一的,这意味着包含合并结果的地图将使之前拥有的元素数量增加一倍,并且容器合并 …
考虑:
struct Point { int x, y; };
int main()
{
const auto [x, y] = Point{};
}
Run Code Online (Sandbox Code Playgroud)
这段代码在C++ 17模式下用gcc 7.1编译得很好,但是这个:
#include <utility>
struct Point { int x, y; };
int main()
{
const auto [x, y] = Point{};
}
Run Code Online (Sandbox Code Playgroud)
给出错误:
bug.cpp: In function 'int main()':
bug.cpp:7:16: error: 'std::tuple_size<const Point>::value' is not an integral constant expression
const auto [x, y] = Point{};
^~~~~~
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?一个编译器错误,或者这是结构化绑定应该如何工作?
我正在尝试使用新的GCC版本7.2.1编译我的项目,并且遇到动态异常规范的问题:
error: ISO C++1z does not allow dynamic exception specifications
MEMORY_ALLOC_OPERATORS(SQLException)
Run Code Online (Sandbox Code Playgroud)
问题是这些错误来自我无法控制的第三方库.
有没有办法解决它?据我所知,我不能告诉编译器用警告替换错误.使用--std=c++14不是一个选项,因为我想使用C++ 1z的新功能.
我最近将 Linux 开发 VM 从 Ubuntu 16.04 升级到 18.04,并注意到一件事发生了变化。这是在 x86-64 上。在 16.04 中,我一直有这样的工作流程,我将使用 gcc(5.4,16.04 中的股票版本)和-fsanitize=addressand构建我正在处理的项目-O0 -g,然后通过 gdb(7.11.1,也是Ubuntu 附带的版本)。这工作得很好,最后,如果 LeakSanitizer 检测到内存泄漏,它会生成一个泄漏报告。
在 18.04 中,这似乎不再起作用;LeakSanitizer 抱怨在 ptrace 下运行:
==5820==LeakSanitizer has encountered a fatal error.
==5820==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1
==5820==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)
Run Code Online (Sandbox Code Playgroud)
然后程序崩溃:
Thread 1 "spyglass" received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
Run Code Online (Sandbox Code Playgroud)
我不确定是什么导致了新行为。在 18.04 上,我使用默认的 gcc (7.3.0) 进行构建,使用-fsanitize=address -O0 -g默认的 gdb (8.1.0)进行调试。可以以某种方式重新启用旧行为吗?或者我是否需要更改我的工作流程并在杀死它以获得泄漏报告之前与程序分离?
我想在我没有 root 访问权限的服务器上安装更新版本的 gcc。我试过
conda install -c creditx gcc-7
哪个不起作用。然后我发现
conda install -c anaconda gcc_linux-64
其实安装了gccv7.3。但是安装成功后,conda环境仍然使用系统gcc at
/usr/bin/gcc
请帮助我,以便我可以使用刚刚安装的 gcc v7.3。
我写的代码在GCC 4.9,GCC 5和GCC 6中是无警告的.它也是一些较旧的GCC 7实验快照的警告(例如7-20170409).但是在最近的快照(包括第一个RC)中,它开始产生关于别名的警告.代码基本归结为:
#include <type_traits>
std::aligned_storage<sizeof(int), alignof(int)>::type storage;
int main()
{
*reinterpret_cast<int*>(&storage) = 42;
}
Run Code Online (Sandbox Code Playgroud)
使用最新的GCC 7 RC进行编译:
$ g++ -Wall -O2 -c main.cpp
main.cpp: In function 'int main()':
main.cpp:7:34: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
*reinterpret_cast<int*>(&storage) = 42;
Run Code Online (Sandbox Code Playgroud)
(有趣的观察是,禁用优化时不会产生警告)
使用GCC 6进行编译完全没有警告.
现在我想知道,上面的代码肯定有类型 - 惩罚,毫无疑问,但是不是std::aligned_storage故意用这种方式?
例如,此处给出的示例代码通常不会对GCC 7发出警告,但仅仅是因为:
std::string 不知何故不受影响,std::aligned_storage 使用偏移量访问.通过改变std::string进int,消除抵消访问std::aligned_storage和删除无关的部分,你会得到:
#include <iostream>
#include <type_traits>
#include <string>
template<class T, std::size_t N>
class static_vector
{ …Run Code Online (Sandbox Code Playgroud) 从Fedora 25升级到26后,默认的gcc版本现在是版本7.1.1,输出gcc -dumpversion已从major.minor.patch更改为major.
新产出:
$ gcc -dumpversion
7
Run Code Online (Sandbox Code Playgroud)
手册说明
-dumpversion
打印编译器版本(例如,3.0,6.3.0或7) - 并且不执行任何其他操作.这是文件系统路径中使用的编译器版本,规格,可以取决于编译器如何配置只有一个数字(主要版本),两个数字用点分隔(主要和次要版本)或三个数字用点分隔(主要,次要和补丁级版本).
我还没有找到更改此编译器配置的位置以包含使用点配置的三个数字.我发现的最接近的是仅限主要版本的配置:
--with-gcc-major-version-only指定GCC应仅使用主文件而不是文件系统路径中的major.minor.patchlevel.
以前,使用Apple LLVM 9.1.0,128 is_lock_free()位结构已经恢复正常.为了得到完全的std::optional支持,我随后升级到了MacPorts gcc 7.3.在我第一次尝试编译时,我遇到了这个臭名昭着的showstopper链接器错误:
Undefined symbols for architecture x86_64:
"___atomic_compare_exchange_16", referenced from:
Run Code Online (Sandbox Code Playgroud)
我知道我可能需要添加-latomic.使用Apple LLVM 9.1.0,我不需要它,我对此非常不满意.如果它是无锁的,您通常不需要链接到任何其他库,单独的编译器就能够处理它.否则,它可能只是基于锁的,需要来自其他库的支持.正如我所担心的那样,添加后-latomic,构建成功,但is_lock_free()返回false.
我认为gcc 7.3及其标准库实现很好.这可能只是我身上的一些配置问题.事实上,我没有做任何配置.我只是安装了MacPorts gcc并完成了.知道我可能缺少什么吗?
以下代码段将在GCC 8+中进行编译,但无法在GCC 7中进行编译。
template <typename... THINGS>
struct A
{
explicit A(THINGS *... things)
{
(..., [thing = things](){}());
}
};
int main()
{
int thing;
const auto thingy = A{&thing};
}
Run Code Online (Sandbox Code Playgroud)
声明的失败是未扩展参数包:parameter packs not expanded with '...'。
检查GCC标准符合性页面,GCC 7中应支持折叠表达式。
我还需要别的标志std=c++17吗?(我没有看到)
标准是否尚未完全实施?(我什么都没有看到,
这表明我可以做这个工作,还是这只是我要解决的GCC 7错误?