The following program complains that "declval() must not be used!" in a static assertion if -Wall is passed. But declval() is only present in the unevaluated context of a decltype specifier. The issue seems to be linked to the generation of the warning message. But the warning message will be present without the static_assert if the function has more than one exit point, such as if(0) throw; or if(0) return; (the latter using -fpermissive). #include <utility> template <typename U> auto foo() -> decltype(std::declval<U>() + std::declval<U>()); template <typename T> decltype(foo<T>()) bar(T) { // if ( 0 ) throw; } int main() { bar(1); }
Narrowing down the cause, the statement { 0; } silences the error but { void(0); } does not.
GCC 6+ produces: <source>: In instantiation of 'decltype (foo<T>()) bar(T) [with T = int; decltype (foo<T>()) = int]': <source>:13:8: required from here <source>:10:1: warning: no return statement in function returning non-void [-Wreturn-type] } ^ And no calling of the static_assert .