[[nodiscard]] 指向函数指针

[[nodiscard]] to a function pointer

本文关键字:指针 函数 nodiscard      更新时间:2023-10-16

我想使用第三方函数,它通过充满函数指针的结构提供其API。 例如:

struct S {
    using p_func1 = int(*)(int, int);
    p_func1 func1;
    using p_func2 = int(*)(char*);
    p_func2 func2;
}

第三方库初始化此结构。需要检查这些函数(func1、func2)的返回值,我希望我能以某种方式在 [[discard]] 属性上显示以确保检查返回值。

有没有办法做到这一点,同时保持结构的 ABI?

编辑:到目前为止,我能想到的最好的就是拥有另一个结构,如下所示:

struct S_wrap {
    S orig;
    [[nodiscard]] int func1(int a, int b){ return orig.func1(a, b); }
    [[nodiscard]] int func2(char* a){ return orig.func2(a); }
}

我希望有更好的东西

您的包装器(或任何包装器)是唯一的方法。该属性适用于函数声明符 id(其名称),而不是函数的类型。因此,使用指针时会丢失它,也不能应用于指针本身:

[dcl.attr.nodiscard]

1 属性令牌nodiscard可以应用于 函数声明中的声明符 ID 或 类或枚举。它最多在每个中出现一次 属性列表和任何属性参数子句都不应存在。

因此,如果函数指针返回一个int,防止丢弃结果的唯一方法是使用某种带有应用了该属性的命名函数(或operator())的包装器。

如果您使用的是GCC,则可以改用__attribute__((warn_unused_result))。与[[nodiscard]]不同,它确实适用于typedefusing

struct S2 {
    using p_func1 = __attribute__((warn_unused_result)) int(*)(int, int);
    p_func1 func1;
    using p_func2 = __attribute__((warn_unused_result)) int(*)(char*);
    p_func2 func2;
};

有趣的是,Clang 接受此代码,但不使用该属性,也不会发出警告。此外,它要求将__attribute__放在前面(如上所述),并且在;之前将其放置在末尾时会拒绝。

您可以改用[[gnu::warn_unused_result]]更进一步:

struct S {
    using p_func1 = int(*)(int, int) [[gnu::warn_unused_result]];
    p_func1 func1;
    using p_func2 = int(*)(char*) [[gnu::warn_unused_result]];
    p_func2 func2;
};

使用 GCC,您可以将[[gnu::warn_unused_result]]放在末尾(如上所示)或开头:

using p_func1 = [[gnu::warn_unused_result]] int(*)(int, int);

就像您在函数上[[nodiscard]]一样。但是,Clang和MSVC(可能还有其他)将拒绝第二种形式。对于第一种形式,Clang 警告忽略的属性,因为它应用于类型。

在此处查看完整示例:https://godbolt.org/z/qEfEeoqeM。