Shouldn't decltype Trigger Compilation of its Argument?
Asked Answered
A

2

16

So I'm perplexed as to how this works. Given:

template <typename T>
int foo(T t) { t.foo(); }

It seems like this call should fail:

decltype(foo(int{ 13 })) fail = 42;

cout << fail << endl;

Instead it just prints:

42

It works this way on all the compilers I have access to. Is this correct behavior? I request a quote from the C++ Standard.

Alleras answered 14/7, 2016 at 12:5 Comment(8)
std::type_info::name() isn't guaranteed to give anything reliable. Does it give anything else in other cases?Lorola
@StoryTeller I've eliminated the type_info from the question. Hopefully this helps clarify the issue. This is a question about decltype and what it's requiring, I was just trying to use type_info to demonstrate the question.Alleras
decltype doesn't really need the full function definition to know the resulting type. (See). So there is no reason to compile anything other than the prototype. But I don't have a standard quote.Lorola
@StoryTeller Wow, that's a great example. This concept is just blowing my mind.Alleras
@StoryTeller sizeof(decltype(expression)) seems a little redundant.Consumable
@Oktalist, It's a poor man's std::is_same. I just wanted a quick and dirty condition for the static assert.Lorola
@StoryTeller I mean sizeof(expression) would be sufficient.Consumable
@Siyual Ugh, grammar, my nemesis. You could probably spend the next month cleaning up my mistakes. But thanks for catching this one.Alleras
S
17

In [dcl.spec] :

For an expression e, the type denoted by decltype(e) is defined as follows:

if e is an unparenthesized id-expression naming an lvalue or reference introduced from the identifier-list of a decomposition declaration, decltype(e) is the referenced type as given in the specification of the decomposition declaration ([dcl.decomp]);

otherwise, if e is an unparenthesized id-expression or an unparenthesized class member access ([expr.ref]), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;

otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;

otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;

otherwise, decltype(e) is the type of e.

The operand of the decltype specifier is an unevaluated operand (Clause [expr]).

(Emphasis mine)

So your foo(int{ 13 }) is never evaluated.

Skite answered 14/7, 2016 at 12:26 Comment(5)
Perfect answer, thanks. I was scared I was going to accept Jesper Juhl's "because I said so" answer.Alleras
I wonder if this really implies that compilation must succeed. E.g. in 1 ? 0 : foo(int{13}) the call is never evaluated, but I wouldn't expect this to compile. (Probably there are some specific rules about what's exactly done in type-checking unevaluated operands... ?)Pinchbeck
If you change the definition of the above function template to template <typename T> auto foo(T t) { t.foo (); }, instantiation of the template seems to happen though - which makes sense to me, since without return type deduction, there is no way for decltype to yield anything. This, of course, ends in a compile time error. Where in the above clause is this behavior reflected? Am I missing something?Forbiddance
@Pinchbeck The term unevaluated operand is a term of art defined by Clause [expr] of the standard, it doesn't just mean "an operand that is not evaluated". The 2nd/3rd operands of the ?: operator are potentially evaluated operands according to [basic.def.odr]. There is a non-normative note in [expr]: "In an unevaluated operand... naming of objects or functions does not, by itself, require that a definition be provided."Consumable
@Forbiddance [decl.spec.auto]: "Return type deduction for a function template with a placeholder in its declared type occurs when the definition is instantiated even if the function body contains a return statement with a non-type-dependent operand. [Note: Therefore, any use of a specialization of the function template will cause an implicit instantiation.]"Consumable
O
5

Expressions in decltype are defined by the standard to not be evaluated, they are only parsed to get the type of the expression.

Opisthognathous answered 14/7, 2016 at 12:15 Comment(9)
Obligatory question to refer to the master document of the universe.Skite
That is one short answer. I'm going to make a comment on it that's longer than the answer itself: I have already established that the compilers I have access to support your statement. So the question is: "Is this correct behavior?" To establish that you'll need to reference something more than your acquired knowledge.Alleras
@JonathanMee of what use is it to you? You are told that the compilers are correct, why do you need a spec reference? Are you going to verify his answer based on the spec text? How certain are you that you are not fooled by the answer into believing that the spec says it, regardless of what the spec actually says?Francescafrancesco
Yes. It's defined by the standard. I don't have the time right now to dig up the exact chapter and verse for you, but it is in there. I may have time to find the exact section for you later, but in the mean time you can go look yourself open-std.org/JTC1/SC22/WG21/docs/papers/2016/n4594.pdfOpisthognathous
@JohannesSchaub-litb I'm assuming you're asking: "Of what use would an official source be?" My answer to that question would be: I don't want to write code that depends on this if it's non-standard behavior that all the compilers I've tried just happened to implement... and may correct next generation. If it's standard behavior though, then I'll expect I can depend on it, and I'll exploit it in code.Alleras
eel.is/c++draft/dcl.type.simple#4 The operand of the decltype specifier is an unevaluated operand (Clause [expr]).Bipartisan
@JonathanMee OK, that makes sense I think. So you are not after a spec text specifically, but would be satisfied by an official statetement, for example by the WG21 website? Note that even the spec does not necessarily determine what officially should be implemented. There are defects in the spec, and the last word is that of the committee.Francescafrancesco
@JohannesSchaub-litb Yeah, I think Niall's comment and Gill Bates answer have satisfied me that this is proper behavior.Alleras
@GillBates you summed up this site perfectlyChoose

© 2022 - 2024 — McMap. All rights reserved.