Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unevaluated operands and auto return type

According with [5/8] and [7.1.7.2/4] (working draft):

  • The operand of the decltype specifier is an unevaluated operand
  • An unevaluated operand is not evaluated

Consider the code below:

#include<type_traits>

struct S { using type = int; };

int f(int i);

template<typename T>
typename T::type g(T);

template<typename T>
auto h(T v) { return v; }

int main() {
    static_assert(std::is_same<decltype(f(42)), int>::value, "!");
    static_assert(std::is_same<decltype(g(S{})), int>::value, "!");
    static_assert(std::is_same<decltype(h(42)), int>::value, "!");
}

It goes without saying that f and g are not evaluated actually.
On the other side, the function h has an auto return type that is deduced from its body, thus from its arguments and thus from the deduced type T.

Can it still be considered an unevaluated operand in this case?
I mean, it seems to me that, in the context of the decltype, the function h must be evaluated to know what the actual return type is.

For I'm quite sure that the working draft is right, the question is: what's wrong in my reasoning?

like image 394
skypjack Avatar asked Aug 18 '16 22:08

skypjack


2 Answers

In order to determine the type denoted by decltype(h(42)), the compiler needs to perform template argument deduction for h and instantiate the template specialization h<int> to examine its body and determine the return type. This is not the same as evaluating h(42); for example, if h contained any side effects such as printing a message, those side effects would not occur.

like image 196
Brian Bi Avatar answered Oct 13 '22 17:10

Brian Bi


Can it still be considered an unevaluated operand in this case? I mean, it seems to me that, in the context of the decltype, the function h must be evaluated to know what the actual return type is.

It's still an Unevaluated context. As Brain's answer(which is the shorter answer) explains.

The C++ standard talks about template argument deduction process, and in substituting arguments for function templates: [temp.deduct/7] (emphasis mine):

The substitution occurs in all types and expressions that are used in the function type and in template parameter declarations. The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside sizeof, decltype, and other contexts that allow non-constant expressions. The substitution proceeds in lexical order and stops when a condition that causes deduction to fail is encountered.

You can start reading from the first paragraph to get more detailed info about template argument deduction.


If you are interested, we can follow the short story

(Note: All quoted paragraphs are partially reproduced, click the section links to see the full paragraph):

Since you already know about decltype and unevaluated contexts, and have quoted relevant sections, we can skip those and start with auto...

[dcl.spec.auto/1]: The auto and decltype(auto) type-specifiers are used to designate a placeholder type that will be replaced later by deduction from an initializer....

A view from placeholder types:

[dcl.spec.auto/2]: The placeholder type can appear with a function declarator... ... If the declared return type of the function contains a placeholder type, the return type of the function is deduced from non-discarded return statements, if any, in the body of the function

About placeholder type deduction:

[dcl.type.auto.deduct/1]: Placeholder type deduction is the process by which a type containing a placeholder type is replaced by a deduced type.

Deducing placeholder return types:

[type.auto.deduct/4]: If the placeholder is the auto type-specifier, the deduced type T' replacing T is determined using the rules for template argument deduction

If the story isn't very clear, you may want to read the entire sections for each quoted paragraph.

like image 1
WhiZTiM Avatar answered Oct 13 '22 17:10

WhiZTiM