Similar problems have arisen in this matter.
Since both the second and third partial specializations correspond to convert<int*, int>
, the compiler will build two test function templates with two partially specialized class templates provided as arguments:
template <class F, class T> void fun2(convert<F*, T, typename std::enable_if< (check<F>::value && check<T>::value), void>::type> ); template <class T> void fun3(convert<int*, T, typename std::enable_if< (check<T>::value), void>::type> );
Then the compiler checks whether one function template is more specialized than another, cross-substituting the set of converted parameters of one function into another and checking whether all arguments of the template can be output. If this works in both directions, then none of the functions is more specialized than the other, and ambiguity arises.
The problem here is that std::enable_if< (check<F>::value && check<T>::value), void>::type>
is an uninformed context that will not be evaluated during this output game arguments. The compiler only checks if the common expressions have the same structural form (where anything before the separator ::
output), and not if they have the same value ( true_type
in this case).
Only by adding the extra check<int>::value
to the third partial specialization does the third specialization become more specialized than the second. Another βfixβ would be to manually put true_type
in the Check
parameter, however the compiler does not do this for you during the output of the argument.
UPDATE In response to Johannes Schaub - litb: you're right, the code with std::check<int>
, placed in std::enable_if
, does not compile on Ideone and MSVC ++ 2010. What can I do from this? According to 14.8.2.4, clause 11 [temp.deduct.partial]
In most cases, all template parameters must have values ββin order to deduct for success, but for partial sequencing, the template parameter can remain without a value if it is not used in the types used for partial ordering. [Note: the template parameter is used in a non-deduced context. - final note] [Example:
template <class T> T f(int);
For OP code, I interpret this that the std::enable_if
expression will be an unused parameter. My assumption would be that Clang 3.1 does not execute some expressions corresponding to Ideone and MSVC ++. I do not understand if, in the context of the above quote, this is required or not by the standard: should only unused template parameters or also unused template expressions be ignored? There are other parts in the standard where phrases like "not requiring implementation for using heroic eff orts" appear. Perhaps Clang is more heroic than MSVC ++ or Ideone in this regard.