在这种情况下“忽略模板参数的属性”是什么意思?

问题描述 投票:0回答:1

我的任务是消除一个大型 C++ 项目中的警告,其中大部分不是我编写的,并且针对以下情况发出了更常见的警告之一:

std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dirToDelete.c_str()), closedir);

警告是

ignoring attributes on template argument 'int (*)(DIR*) {aka int(*)(__dirstream*)}' [-Wignored-attributes]
std::unique_ptr dir(opendir(dirToDelete.c_str()), closedir);

DIR
opendir
closedir
都在标准头
dirent.h
中定义。)

我知道这段代码的作用,并且它正在工作,但是警告是什么意思?编译器引用的被忽略的属性是什么?这意味着什么?

c++ gcc-warning
1个回答
5
投票

被忽略的属性很可能是GCC的

nonnull
,这表明参数不能为空指针。您可以使用以下代码重现此警告:

#include <memory>

void closedir(struct DIR*) __attribute__((nonnull(1)));

std::unique_ptr<struct DIR, decltype(&closedir)> dir(nullptr, &closedir);
<source>:5:48: warning: ignoring attributes on template argument 'void (*)(DIR*)' 
               [-Wignored-attributes]
    5 | std::unique_ptr<struct DIR, decltype(&closedir)> dir(nullptr, &closedir);
      |

问题是函数指针的属性在用作模板参数时会被丢弃。如果您继续使用函数指针,则必须删除该属性(请参阅从函数指针或引用中删除 __attribute__((...))),或者您必须抑制警告(请参阅选择性删除使用 GCC 的警告消息)。

解决方案

一般来说,您不应在删除器是函数指针的情况下创建智能指针,因为这会增加智能指针的大小

1),并妨碍优化2)。您正在创建一个 std::unique_ptr

,它可以保存与 
closedir
 具有相同签名的删除器,但删除器原则上可以是任何函数。

相反,更喜欢自定义类型作为删除器:

#include <memory> // Exposition-only, obviously use #include <dirent.h> void closedir(struct DIR*) __attribute__((nonnull(1))); // Note 1: In C++20, you could also decltype(lambda) as a deleter type. struct closedir_deleter { // Note 2: Consider adding noexcept. void operator()(struct DIR* d) const { closedir(d); } }; // Note 3: You can create a type alias for this specialization of std::unique_ptr. // Note 4: It is no longer necessary to pass a deleter as an argument to the // constructor, because the deleter is default-constructible, and not a pointer. std::unique_ptr<struct DIR, closedir_deleter> dir;

参见编译器资源管理器中的实时示例

这不仅是更好的做法,它还为您消除了警告。


1) 这是因为std::unique-ptr

必须存储指针本身以及函数指针。对于简单的空删除器,它不必存储任何内容。

2) 如果编译器不知道函数指针的确切值,则无法将函数指针优化为直接函数调用。众所周知,函数指针的内联性能通常很差。

© www.soinside.com 2019 - 2024. All rights reserved.