I have a functional object which is a wrapper around another function:
template <typename FuncT>
class Wrapper
{
private:
FuncT funcToWrap;
public:
Wrapper(FuncT ftw) : funcToWrap(ftw){};
template<typename ...ARG>
typename std::result_of<FuncT(ARG&&...)>::type operator()(ARG&&... args){
return funcToWrap(std::forward<ARG>(args)...);
}
};
int main(){
std::function<void()> testfunc = [](){ std::cout << "Test" << std::endl; };
Wrapper<decltype(testfunc)> test{testfunc};
test();
}
What I would like to do is to mark the operator()
as [[nodiscard]]
if the std::result_of<FuncT(ARG&&...)>::type
is not void
.
What I have noticed is that when I do put the [[nodiscard]]
in case of the template evaluation of return type to void
, it will simply get ignored by my compiler.
Is this the behaviour I can rely on, is it in any way standarized?
[ Note: A nodiscard call is a function call expression that calls a function previously declared
nodiscard
, or whose return type is a possibly cv-qualified class or enumeration type markednodiscard
. Appearance of a nodiscard call as a potentially-evaluated discarded-value expression is discouraged unless explicitly cast tovoid
. Implementations should issue a warning in such cases. This is typically because discarding the return value of a nodiscard call has surprising consequences. — end note ]
My reading of this paragraph gives that, given
[[nodiscard]] void f() {}
even
f();
should issue a warning. You have to explicitly cast to void
as in
(void) f();
to suppress it. So no, this is not guaranteed by the standard.
It seems to me that the standard simply overlooked this subtlety.