Does this SFINAE technique relying on empty parameter packs work?

75 views
Skip to first unread message

Johannes Schaub

unread,
Sep 15, 2013, 7:38:35 AM9/15/13
to std-dis...@isocpp.org
I wonder whether the following technique is Standard C++

template<bool>
struct Sfinae { };

template<>
struct Sfinae<true> { typedef int type; };

To SFINAE the following function

template<typename T,
typename Sfinae<is_foobar<T>::value>::type...>
void f(T);

int main() { f(0); }

The "..." is the key of this technique which have been used by some
people. However, at least one compiler does not like this (Clang), and
according to my understanding of the spec, I cannot see how it works:

When a trailing template parameter pack has not otherwise been
deduced, it will be deduced as an empty parameter pack, 14.8.1p3 says.
Substitution of parameters by their deduced arguments happens after
deduction.

I see an ambiguity in the spec with that. Does the substitution of "T"
into the pattern of the parameter pack happen first, and is the pack
substituted by the individual parameters afterwards, or does the
substitution of the arguments corresponding to the parameter pack
happen first, and then the subtitution of "T" into the generated
sequence of non-pack parameters? In the latter option, there will be
no instance of "T" left to substitute, and so we can *never* actually
SFINAE fail.

Someone up into the detail and can explain what is intended?

David Krauss

unread,
Sep 15, 2013, 9:37:43 AM9/15/13
to std-dis...@isocpp.org, schaub....@googlemail.com
SFINAE is applied when template argument deduction fails to produce a valid signature (§14.8.3). So the question is whether argument deduction is required to observe the defect, required not to, or that there is no requirement.

It appears that the the invalid type is required to be formed, hence SFINAE is guaranteed. §14.8.2/5:

When all template arguments have been deduced or obtained from default template arguments, all uses of template parameters in the template parameter list of the template and the function type are replaced with the corresponding deduced or default argument values. If the substitution results in an invalid type, as described above, type deduction fails.

If that isn't convincing, then try ¶7 (although "used" perhaps needs to be "occurs"; I'm not sure what it means for an expression to be used):

The substitution occurs in all types and expressions that are used in the function type and in template parameter declarations.

It doesn't matter whether a use of a template parameter in the template parameter list is ultimately unused. All substitutions must be performed.

Perhaps you could weasel your way through this with selective interpretation. But although the pack is allowed to match zero arguments, when it does so it doesn't cease to exist. The pack isn't replaced with a finite sequence of parameters which then match arguments. Something like that would need to happen to make it go away before SFINAE could fail.
Reply all
Reply to author
Forward
0 new messages