'[[nodiscard]] to a function pointer
I want to use a third party functions, which provides its API through a struct full of function pointers. for example:
struct S {
using p_func1 = int(*)(int, int);
p_func1 func1;
using p_func2 = int(*)(char*);
p_func2 func2;
}
The third party library initializes this struct.
The return values of those functions (func1, func2) needs to be checked, and I was hoping I could somehow manifest on the [[discard]] attribute to make sure the return values are checked.
Is there any way to do this, while maintaining the ABI of the struct?
Edit: So far, the best I could come up with is having another struct, like so:
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); }
}
I'm hoping there's something better
Solution 1:[1]
Your wrapper (or any wrapper) is the only way to go. The attribute applies to the function declarator-id (its name), not the function's type. So it's lost when using a pointer, nor can it be applied to the pointer itself:
[dcl.attr.nodiscard]
1 The attribute-token
nodiscardmay 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.
So if the function pointers are returning an int, the only way to prevent discarding the result is to use some sort of wrapper with a named function (or operator()) that has the attribute applied.
Solution 2:[2]
If you are using GCC you may use __attribute__((warn_unused_result)) instead. Unlike [[nodiscard]] it does work on typedef or 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;
};
Interestingly, Clang accepts this code but doesn't use the attribute and will not issue warnings. Also, it requires the __attribute__ to be placed at the front (as above), and will reject when it is placed at the end, before ;.
You can go further by using [[gnu::warn_unused_result]] instead:
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;
};
With GCC you can place the [[gnu::warn_unused_result]] both at the end (as shown above) or at the beginning:
using p_func1 = [[gnu::warn_unused_result]] int(*)(int, int);
as you would with [[nodiscard]] on a function. However, Clang and MSVC (and probably other) will reject the second form. For the first form, Clang warns about ignored attributes since it is applied to type.
See full sample here: https://godbolt.org/z/qEfEeoqeM.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | StoryTeller - Unslander Monica |
| Solution 2 | Adam Badura |
