Reputation: 33
While I was reading about SFINAE on cppreference.com I've come across this snippet I just cannot grasp:
template <int I> void div(char(*)[I % 2 == 0] = 0)
So what the hell is
char(*)[I % 2 == 0] = 0
It looks like a pointer to a function that returns char but what is the square bracket with a bool in it. Is it a real thing or is it just some silly artifical example?
Upvotes: 3
Views: 199
Reputation: 25663
What you see is SFINAE in old fashion style.
Background: SFINAE: Substitution Failure Is Not An Error
When you try to instantiate a template, it checks if the template can be instantiated without errors. If an error occurs, simply nothing will happen, the current tried template will simply ignored. Typically you have two or more template definitions but only one in a time can be instantiated without an error.
In your case, a array will be created and if I is even, the result is an array with size zero. This is a compile error, but as used as a template declaration, it is allowed to fail and will be ignored. As this, you can use such an statement to select which template will be instantiated depending on a parameter.
The syntax in detail:
template <int I> void div(char(*)[I % 2 == 0] = 0)
We have a template, takes one parameter: an int I. Then the template is defining a function, which takes an pointer to an array of char with a size of "I % 2 == 0", which results in a bool to int conversion from the logic. As this, if I is even, the result is zero -> SFINAE will fail, instance ignored, if I is odd, you get true -> converted to 1. This means, you create a pointer to a char pointer array with size 1. OK, the instance will be created. After having the pointer it will be default initialized to 0.
Here we see that an even or odd I can be used to select which of both ( or more ) templates will be instantiated.
In more "modern" C++ we see std::enable_if to select which template will be instantiated. This makes it more readable. But before c++11 c++ did not have this. So the need to generate an error for SFINAE was often done by creating arrays of negative or zero size. It is a common hack for SFINAE in old style code.
Upvotes: 4
Reputation: 85907
Maybe it'll become clearer if you put the parameter name in:
void div(char (*x)[I % 2 == 0] = 0)
x
is a pointer to an array of size 1
(for true) or 0
(for false), defaulting to nullptr
.
But parameter names are optional in C++, so if the function doesn't use x
, it can just leave out the name.
Upvotes: 3
Reputation: 3047
char(*)[I % 2 == 0] = 0
is a pointer on an array of char of size 1 when I is even and 0 when I is odd, and the pointer is defaulted to 0
because you can't create array with size equal to 0, this overload can only be called when I is even
Upvotes: 2