Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any guarantee on the order of substitution in a function template after type deduction?

Consider this function template:

template<typename T>
typename soft_error<T>::type foo(T, typename hard_error<T>::type)
{ }

After deducing type T from the type of the first argument in the call to foo(), the compiler will proceed to substitute T and instantiate the function signature.

If substitution for the return type gets executed first, causing a simple substitution failure, the compiler will discard this function template when computing the overload set and search for other viable overloads (SFINAE).

On the other hand, if substitution for the second function parameter occurs first, causing a hard error (e.g. because of a substitution failure in a non-immediate context), the entire compilation would fail.

QUESTION: Is there any guarantee on the order in which substitution will be performed for the function parameters and return types?


NOTE: This example seems to show that on all major compilers (VC11 was tested separately and gave identical results) substitution for the return type occurs before substitution for the parameter types.

like image 458
Andy Prowl Avatar asked Mar 17 '13 15:03

Andy Prowl


Video Answer


1 Answers

[NOTE: This was not originally meant to be a self-answered question, but I happened to find out the solution while crafting the question]


Is there any guarantee on the order in which substitution will be performed for the function parameters and return types?

Not in the current standard.

However, this Defect Report (courtesy of Xeo) shows that this is indeed intended to be the case. Here is the proposed new wording for Paragraph 14.8.2/7 of the C++11 Standard (which has become part of the n3485 draft):

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. [...]

As correctly pointed out by Nicol Bolas in the comments to the question, lexical order means that a trailing return type would be substituted after the parameter types, as shown in this live example.

like image 89
Andy Prowl Avatar answered Sep 23 '22 05:09

Andy Prowl