简体   繁体   中英

[[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

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 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.

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.

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM