Compiler: TDM-GCC-5.1.0 (SJLJ unwinding)
I was playing around with declval
and I noticed that I was unable to use it in a context where it should work: as an argument to typeid()
.
In the following code, I use declval
for one of it's primary use cases: to obtain the return type of a method without going through an instance. The error I get is the static_assert message of declval
, but that should be impossible because typeid()
doesn't evaluate it's argument in this case:
#include <typeinfo>
#include <utility>
struct Foo
{
int func();
};
int main()
{
typeid(std::declval<Foo>().func());
}
This doesn't compile for me (when compiled with -std=c++14
). My only guess is that either I've found a compiler bug, or I've done something obviously wrong and I can't see it. If it is the latter, my apologies.
EDIT:
Thanks to ildjarn for helping me out, the solution is to use decltype
, so the last line of code becomes:
typeid(decltype(std::declval<Foo>().func()));
and this works nicely. However, now my question becomes: how come? Both typeid()
and decltype()
are unevaluated contexts, so I'm not sure what the difference is.
typeid(decltype(std::declval<Foo>().func()));
– Instateexpression
is not a glvalue expression of polymorphic type,typeid
does not evaluate the expression[.]". I'm thinking compiler bug. – Veiledtypeid
does not evaluate the expression, and thestd::type_info
object it identifies represents the static type of the expression." Exactly as doesdecltype
, which fixes it. – Instatedecltype
calls the other version oftypeid
(labeled "(1)" in cppreference). But "version 2" should also work as-is, since it does not evaluate its argument. – Veileddecltype
, which works, should be semantically identical to "version 2", which doesn't. "Yup" meaning "yup, definitely compiler bug." – Instatetypeid
will evaluate its parameter by design, namely when used with polymorphic types. It may be best to wrapdeclval
indecltype
whenever usingtypeid
, to guarantee an unevaluated context. – Janeanjaneczka