Re: SFINAE rules and hard errors in types and expressions
Am 27.11.2010 06:40, schrieb Nikolay Ivchenkov:
According to N3126 - 14.8.2,
At certain points in the template argument deduction process it is
necessary to take a function type that makes use of template
parameters and replace those template parameters with the
corresponding template arguments. This is done at the beginning of
template argument deduction when any explicitly specified template
arguments are substituted into the function type, and again at the end
of template argument deduction when any template arguments that were
deduced or obtained from default arguments are substituted.
The substitution occurs in all types and expressions that are used
in the function type and in template parameter declarations.
[...] Only invalid types and expressions in the immediate context of
the function type and its template parameter types can result in a
deduction failure.
IMO, these rules leave open the question of what may happen if an
error would occur in both immediate and non-immediate contexts.
I agree with that interpretation, this is unspecified.
[..]
Here instantiation of Z<T> with int is ill-formed (the error occurs in
non-immediate context). Further analysis whether Z<T> (where T is int)
has member 'value' is pointless. IMO, the program is ill-formed
(though, GNU C++ 4.5.0 does not issue an error here).
template<int>
struct X
{ typedef int type; };
template<class T>
struct Y
{};
template<>
struct Y<bool>
{ static const int value = 0; };
template<class T>
struct Z
{ static int const value = Y<T>::value; };
template<class T>
typename X<Y<T>::value + Z<T>::value>::type f(T);
int f(...);
int main()
{
sizeof f(0);
}
Here expression Y<T>::value (where T is int) is directly ill-formed
and instantiation of Z<T> with int is ill-formed (the error occurs in
non-immediate context). I see 4 possible options:
1) this program is ill-formed and no diagnostic is required (i.e., the
behavior is undefined);
2) it is unspecified or implementation-defined whether the deduction
fails, and the program may be treated as well-formed or ill-formed;
3) an implementation shall treat the program as well-formed;
4) an implementation shall treat the program as ill-formed.
What option is supposed to be right? IMO, this program should be
treated as ill-formed.
Now let's consider the following program:
typedef char size_1[1];
typedef char size_2[2];
template<class T, class = typename T::type>
size_1&f(T);
size_2&f(...);
#define STATIC_ASSERT(expr) static_assert(expr, #expr)
int main()
{
STATIC_ASSERT(sizeof f(0) == 2);
}
Should it be treated as ill-formed because the default template-
argument would be invalid? I don't think so. And GNU C++ 4.5.0
compiles this sample successfully. However, AFAICS, according to the
current C++0x specification (N3126), such program shall be considered
as ill-formed, because "Only invalid types and expressions in the
immediate context of the function type and its template parameter
types can result in a deduction failure", and the default template-
argument is neither a part of the function type nor a part of
function's template parameter type.
I don't think that the standard currently requires that the program is
ill-formed. As of 14.7.1/5 a compiler is allowed to ignore further class
template instantiations during overload resolution in certain situations. There
is currently no explicit requirement that when a compiler has found an invalid
construct in the immediate context as of 14.8.2 it shall proceed to instantiate
all other otherwise required class template instantiations of the declaration.
Thus, I would say that it is unspecified whether the program is ill-formed or
well-formed, because the standard does not say that a compiler has to
instantiate Y<int> before it instantiates Z<int>.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]