Consider this snippet:
#include <utility>
template <typename U>
auto foo() -> decltype(std::declval<U>() + std::declval<U>());
template <typename T>
decltype(foo<T>()) bar(T)
{}
int main()
{
bar(1);
return 0;
}
This fires a warning and a static assertion failure in all versions of GCC I tried it on (4.7.3, 4.8.1, 4.9-some-git) when compiled with -Wall -Wextra
. For instance, this is the output of 4.8.1:
main.cpp: In instantiation of ‘decltype (foo<T>()) bar(T) [with T = int; decltype (foo<T>()) = int]’: main.cpp:12:7: required from here main.cpp:8:2: warning: no return statement in function returning non-void [-Wreturn-type] {} ^ In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/bits/move.h:57:0, from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/bits/stl_pair.h:59, from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/utility:70, from main.cpp:1: /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/type_traits: In instantiation of ‘typename std::add_rvalue_reference< <template-parameter-1-1> >::type std::declval() [with _Tp = int; typename std::add_rvalue_reference< <template-parameter-1-1> >::type = int&&]’: main.cpp:8:2: required from ‘decltype (foo<T>()) bar(T) [with T = int; decltype (foo<T>()) = int]’ main.cpp:12:7: required from here /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/type_traits:1871:7: error: static assertion failed: declval() must not be used! static_assert(__declval_protector::__stop,
If one either disables the warnings or supplies bar
with a return statement, e.g.,
template <typename T>
decltype(foo<T>()) bar(T a)
{
return a + a;
}
the assertion failure disappears. Clang++ 3.3 does not fire assertion errors in any case. Is this standard-conforming behaviour from GCC?
My copy of GCC 4.9 built in early June compiles it without complaint as long as I add return {};
or throw;
inside the function. With no return
, it does fire that static assertion. This is certainly a bug, but only a minor one, since the function only "crashes" upon execution.
I have seen that error when trying to execute declval()
in a constant expression, so something like that may be happening in your case. The "cannot be used" is presumably referring to ODR-use or using the result.
Perhaps in the absence of any statement it tried to manufacture one with the content of the decltype
. Adding even a simple statement like 0;
silences the spurious error. (But static_assert( true, "" )
or even void(0)
are insufficient.)
Filed a GCC bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With