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