[[nodiscard]] 到一个函数指针
[[nodiscard]] to a function pointer
我想使用第三方函数,它通过充满函数指针的结构提供 API。例如:
struct S {
using p_func1 = int(*)(int, int);
p_func1 func1;
using p_func2 = int(*)(char*);
p_func2 func2;
}
第三方库初始化这个结构。
需要检查这些函数(func1、func2)的 return 值,我希望我能以某种方式在 [[discard]]
属性上显示以确保检查 return 值。
有没有办法做到这一点,同时保持结构的 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); }
}
我希望有更好的东西
您的包装器(或任何包装器)是唯一的出路。该属性适用于函数 declarator-id(它的名称),而不是函数的类型。所以在使用指针的时候就丢失了,也不能应用到指针本身:
[dcl.attr.nodiscard]
1 The attribute-token nodiscard
may be applied to the
declarator-id in a function declaration or to the declaration of a
class or enumeration. It shall appear at most once in each
attribute-list and no attribute-argument-clause shall be present.
因此,如果函数指针返回 int
,防止丢弃结果的唯一方法是使用某种带有具有属性的命名函数(或 operator()
)的包装器应用。
如果您使用的是 GCC,则可以改用 __attribute__((warn_unused_result))
。与 [[nodiscard]]
不同,它确实适用于 typedef
或 using
:
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。
我想使用第三方函数,它通过充满函数指针的结构提供 API。例如:
struct S {
using p_func1 = int(*)(int, int);
p_func1 func1;
using p_func2 = int(*)(char*);
p_func2 func2;
}
第三方库初始化这个结构。
需要检查这些函数(func1、func2)的 return 值,我希望我能以某种方式在 [[discard]]
属性上显示以确保检查 return 值。
有没有办法做到这一点,同时保持结构的 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); }
}
我希望有更好的东西
您的包装器(或任何包装器)是唯一的出路。该属性适用于函数 declarator-id(它的名称),而不是函数的类型。所以在使用指针的时候就丢失了,也不能应用到指针本身:
[dcl.attr.nodiscard]
1 The attribute-token
nodiscard
may be applied to the declarator-id in a function declaration or to the declaration of a class or enumeration. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present.
因此,如果函数指针返回 int
,防止丢弃结果的唯一方法是使用某种带有具有属性的命名函数(或 operator()
)的包装器应用。
如果您使用的是 GCC,则可以改用 __attribute__((warn_unused_result))
。与 [[nodiscard]]
不同,它确实适用于 typedef
或 using
:
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。