Strange SFINAE code - c++

I found this code in conjunction to SFINAE:
template<int I> void div(char(*)[I % 2 == 0] = 0) {
// this overload is selected when I is even
}
template<int I> void div(char(*)[I % 2 == 1] = 0) {
// this overload is selected when I is odd
}
How does it work? It looks like an unnamed parameter array but I don't understand how the subscripting helps in overload resolution.

Array bounds in C++ cannot be zero. If the expression (e.g., I % 2 == 0) is false, that's converted to zero, resulting in an invalid type and therefore substitution failure.
Essentially, it's an obfuscated version of std::enable_if.

Remember this is called like this: div<1234>() => first overload is called.
To understand you only need to look at the argument:
char(*)[I % 2 == 0] = 0
This means it is pointer to an array of chars. This array has the default value 0. This means you could also do char a[] = "hello world"; div<1234>(a);
I % 2 == 0 is evaluated at compile time. You should know what it does. Even integers make this true, Odd integers make this false. True evaluates to 1, false evaluates to 0. However there is no such thing as an array with zero elements. This is what you call a SFINAE error. It doesn't mean it is a fundamental error, just that the blanks in the template could not be substituted adequately. The template doesn't match.

As mentioned by T.C. since you cannot have arrays of 0 element, when the condition is false, the boolean false is converted to 0: the type becomes char (*)[0] (pointer to a char array of size 0) and this triggers SFINAE.
Now, in a more conventional (and readable) way, you would usually let std::enable_if do the job:
template <int I, std::enable_if_t<I%2>* = nullptr>
div() {
std::cout << "I (" << I <<") am odd." << std::endl;
}
template <int I, std::enable_if_t<!(I%2)>* = nullptr>
div() {
std::cout << "I (" << I <<") am even." << std::endl;
}
As demonstrated here on Coliru.

Related

How to pass parameters to this function : void func(int rows, int columns, int matrix[rows][columns]) [duplicate]

In the following code
#include<iostream>
template<typename T,size_t N>
void cal_size(T (&a)[N])
{
std::cout<<"size of array is: "<<N<<std::endl;
}
int main()
{
int a[]={1,2,3,4,5,6};
int b[]={1};
cal_size(a);
cal_size(b);
}
As expected the size of both the arrays gets printed. But how does N automatically gets initialized to the correct value of the array-size (arrays are being passed by reference)? How is the above code working?
N does not get "initialized" to anything. It is not a variable. It is not an object. N is a compile-time constant. N only exists during compilation. The value of N as well as the actual T is determined by the process called template argument deduction. Both T and N are deduced from the actual type of the argument you pass to your template function.
In the first call the argument type is int[6], so the compiler deduces that T == int and N == 6, generates a separate function for that and calls it. Let's name it cal_size_int_6
void cal_size_int_6(int (&a)[6])
{
std::cout << "size of array is: " << 6 << std::endl;
}
Note that there's no T and no N in this function anymore. Both were replaced by their actual deduced values at compile time.
In the first call the argument type is int[1], so the compiler deduces that T == int and N == 1, generates a separate function for that as well and calls it. Let's name it cal_size_int_1
void cal_size_int_1(int (&a)[1])
{
std::cout << "size of array is: " << 1 << std::endl;
}
Same thing here.
Your main essentially translates into
int main()
{
int a[]={1,2,3,4,5,6};
int b[]={1};
cal_size_int_6(a);
cal_size_int_1(b);
}
In other words, your cal_size template gives birth to two different functions (so called specializations of the original template), each with different values of N (and T) hardcoded into the body. That's how templates work in C++.
It works because the type of a is "array of length 6 of int" and the type of b is "array of length 1 of int". The compiler knows this, so it can call the correct function. In particular, the first call calls the template instance cal_size<6>() and the second call calls cal_size<1>(), since those are the only template instantiations which match their respective arguments.
If you attempted to call an explicit template instance, it would only work if you got the size right, otherwise the arguments wouldn't match. Consider the following:
cal_size(a); // ok, compiler figures out implicitly that N=6
cal_size<int, 6>(a); // also ok, same result as above
cal_size<int, 5>(a); // ERROR: a is not of type "array of length 5 of int"
when you declare int a[] = {1,2,3} it is the same as (or will be rewritten as) int a[3] = {1,2,3} since the templated function is receiving argument in form of T a[N], then N will have value of 3.

When do I need to specify the type a template

I've written a simple template to find the smallest number in a list of arguments.
template<typename T>
T smallerList(T a, T b) {
std::cout << "a= " << a << " b= " << b << std::endl;
return a < b ? a : b;
}
template<typename T, typename... Rest>
T smallerList(const T& param0, const Rest&... rest) {
T temp = smallerList(rest...);
return param0 < temp ? param0 : temp;
}
int main()
{
// Works, returns "3"
std::cout << "Smaller: " << smallerList(4, 5, 6, 3, 7) << std::endl;
// Sort of works, returns "2". Should be "2.14".
std::cout << "Smaller: " << smallerList(3.14, 43534, 100.2, 3.13, 2.14) << std::endl;
}
For some reason the second function call returns 2 instead of 2.14. Why does this happen?
I've printed the intermediate values of the variables and they are correct. It seems like an implicit conversion is happening when smallerList returns.
I was able to solve this by changing the line
T temp = smallerList(rest...);
into
T temp = smallerList<T>(rest...);
After this change the function prints 2.14 as expected.
My question: Why do I need to specify the type? I thought that templates functions are "created" for each type that is called?
Ok, I don't know how to really help you, because I don't know what exact logic you want to have. But at you variadic template you allow type mixing, and in your 2nd vector, you pass one integer - 43534, so when 2.14 back propagates when recursion rolls back you get something like
return (int)(43534 < 2.14? 43534 : 2.14);
Because 43534 will be param0, and you take return type of param0, and 2.14 gets converted to 2. Next it gets converted back to a float but you don't see it.
You either need to check whether the types of the parameters are the same, or come up with some logic to promote your arguments. Not that it does work like you expect if you use 43534.0 because it won't be an int anymore.
EDIT:
T temp = smallerList<T>(rest...); this does not really help you, it changes the behaviour, forcing a cast on each argument to type of the 1st argument. Well it gets more consistent. But try:
smallerList(7, 10.5, 10, 3.13, 2.14)
It will break. I am not 100% sure why, but I guess it couldn't match end of recursion, because it would look for smallerList(int, float) and your terminator template won't match.
You would need something like:
template<typename T, typename U>
T smallerList(T a, U b) {
std::cout << "a= " << a << " b= " << b << std::endl;
return a < b ? a : b;
}
It also discards 2nd type, so you will have type conversions, but if your goal is to keep the the type of 1st argument it is consistent.

C++ postfix expression undefined vs unspecified behaviour

Apologies in advance, I know the general topic of evaluation order has had a lot of SO questions on it already. However, having looked at them, I want to clarify a few specific points that I don't think amount to a duplication of anything. Suppose I have the following code:
#include <iostream>
auto myLambda(int& n)
{
++n;
return [](int param) { std::cout << "param: " << param << std::endl; };
}
int main()
{
int n{0};
myLambda(n)(n);
return 0;
}
The program above outputs "n: 0" when I compile it. Here we have unspecified ordering at play: it could have just as easily output "n: 1" had a different evaluation order taken place.
My questions are:
What exactly is the sequencing relationship at play during the final function invocation above (i.e. the lambda-expression invocation), between the postfix expression myLambda(0), its argument n, and the subsequent function call itself?
Is the above an example of undefined or unspecified behaviour - and why exactly (with reference to the standard)?
If I changed the lambda code to [](int param) { std::cout << "hello" << std::endl } (i.e. made the outcome independent of its parameter and thus any evaluation order decisions, making behaviour deterministic) would the answer to 2) above still be the same?
EDIT: I've change the lambda parameter name from 'n' to 'param' because that seemed to be causing confusion.
Ironically (since the example uses C++11 features, and other answers have been distracted by that) the logic that makes this sample have unspecified behaviour dates back to C++98, Section 5, para 4
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.
Essentially the same clause exists in all C++ standards although, as noted in comment by Marc van Leeuwen, recent C++ standards no longer use the concept of sequence points. The net effect is the same: within a statement, the order or evaluation of operands of operators and subexpressions of individual expressions remains unspecified.
The unspecified behaviour occurs because an expression n is evaluated twice in the statement
myLambda(n)(n);
One evaluation of the expression n (to obtain a reference) is associated with the first (n) and another evaluation of an expression n (to obtain a value) is associated with the second (n). The order of evaluation of those two expressions (even though they are, optically, both n) is unspecified.
Similar clauses exist in ALL C++ standards, and have the same result - unspecified behaviour on the statement myLambda(n)(n), regardless of how myLambda() implemented
For example, myLambda() could be implemented in C++98 (and all later C++ standards, including C++11 and later) like this
class functor
{
functor() {};
int operator()(int n) { std::cout << "n: " << n << std::endl; };
};
functor myLambda(int &n)
{
++n;
return functor();
}
int main()
{
int n = 0;
myLambda(n)(n);
return 0;
}
since the code in the question is just a (C++11) technique (or shorthand) for achieving the same effect as this.
The above answers OP's questions 1. and 2. The unspecified behaviour occurs in main(), is unrelated to how myLambda() itself is implemented.
To answer the OP's third question, the behaviour is still unspecified if the lambda (or the functor's operator()) in my example) is modified to not access the value of its argument. The only difference is that the program as a whole produces no visible output that might vary between compilers.
The n in the definition of the lambda is a formal argument to the function that the lambda defines. It has no connection to the argument to myLambda that's also named n. The behavior here is dictated entirely by the way these two functions are called. In myLambda(n)(n) the order of evaluation of the two function arguments is unspecified. The lambda can be called with an argument of 0 or 1, depending in the compiler.
If the lambda had been defined with [=n]()... it would behave differently.
I didn't manage to find proper reference to standard but I see that it has similar behavior to argument evaluation order asked here and the order of function arguments evaluation is not defined by the standard:
5.2.2 Function call
8 [ Note: The evaluations of the postfix expression and of the argument expressions are all unsequenced relative to one another. All side effects of argument expression evaluations are sequenced before the function
is entered (see 1.9). —end note ]
So here's how it goes inside the calls on different compilers:
#include <iostream>
#include <functional>
struct Int
{
Int() { std::cout << "Int(): " << v << std::endl; }
Int(const Int& o) { v = o.v; std::cout << "Int(const Int&): " << v << std::endl; }
Int(int o) { v = o; std::cout << "Int(int): " << v << std::endl; }
~Int() { std::cout << "~Int(): " << v << std::endl; }
Int& operator=(const Int& o) { v = o.v; std::cout << "operator= " << v << std::endl; return *this; }
int v;
};
namespace std
{
template<>
Int&& forward<Int>(Int& a) noexcept
{
std::cout << "Int&: " << a.v << std::endl;
return static_cast<Int&&>(a);
}
template<>
Int&& forward<Int>(Int&& a) noexcept
{
std::cout << "Int&&: " << a.v << std::endl;
return static_cast<Int&&>(a);
}
}
std::function<void(Int)> myLambda(Int& n)
{
std::cout << "++n: " << n.v << std::endl;
++n.v;
return [&](Int m) {
std::cout << "n: " << m.v << std::endl;
};
}
int main()
{
Int n(0);
myLambda(n)(n);
return 0;
}
GCC g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out and MSVC
Int(int): 0
Int(const Int&): 0
++n: 0
Int&: 0
Int&: 0
Int(const Int&): 0
n: 0
~Int(): 0
~Int(): 0
~Int(): 1
So it creates variable and copies it to pass to returned lamba.
Clang clang++ -std=c++14 main.cpp && ./a.out
Int(int): 0
++n: 0
Int(const Int&): 1
Int&: 1
Int&: 1
Int(const Int&): 1
n: 1
~Int(): 1
~Int(): 1
~Int(): 1
Here it creates variable evaluates function and then passees copy the lamba.
And the order of evaluation is:
struct A
{
A(int) { std::cout << "1" << std::endl; }
~A() { std::cout << "-1" << std::endl; }
};
struct B
{
B(double) { std::cout << "2" << std::endl; }
~B() { std::cout << "-2" << std::endl; }
};
void f(A, B) { }
int main()
{
f(4, 5.);
}
MSVC and GCC:
2
1
-1
-2
Clang:
1
2
-2
-1
As in clang order is forward and the argument to lambda is passed after evaluation of the function's argument
Ṫhe behaviour is unspecified, because in the function call (myLambda(n))(n) the postfix expression (which I gave an extra redundant pair of parentheses) is unsequenced relative to the argument expression n (the rightmost one). However there is no undefined behaviour, because the modification of n takes place inside the function call myLambda(n). The only definite sequencing relation is that both evaluating myLambda(n) and the final n are obviously sequenced before the actual call of the lambda. For the final question, is the lambda chooses to completely ignore its argument, then the behaviour is no longer unspecified: though it is unspecified what value gets passed as parameter, there is no observable difference either way.
The order in which sub expressions are evaluated is unspecified and can vary apart from the operators &&, ||,? and ",".
The compiler knows both function prototyps myLambda and also the return lambda(extracted from the return type). Cause my first sentence the compiler is free which expression he evaluates first. Thats why you should never call to functions in on expression which have additional side effects.

Constexpr is this correct behaviour?

I'm not sure this is correct behaviour. So I hadn't messed with constexpr before and want to make sure I'm not misunderstanding something about the spec. Testing in the way MSDN mentions to test it. If I put a breakpoint in the function and it gets skipped then it was evaluated at compile time. Is the behaviour below normal?
https://msdn.microsoft.com/en-us/library/dn956974.aspx
It only seems to work with optimization on period.
It only works if I set the value to a constexpr variable or in specific use cases that have NOTHING to do with the input variable.
So for some reason this works
constexpr unsigned int factorial(unsigned int n)
{
return n <= 1 ? 1 : n*factorial(n - 1);
}
constexpr unsigned int value = factorial(5);
std::cout << value << std::endl;
but this gets ran at run time
constexpr unsigned int factorial(unsigned int n)
{
return n <= 1 ? 1 : n*factorial(n - 1);
}
std::cout << factorial(5) << std::endl;
Seems kinda inconvenient to have to make a constexpr variable. It seems to work in some other specialized cases.
switch (fnv1a("Hello"))
{
case fnv1a("GoodBye"):
std::cout << "GoodBye" << std::endl;
break;
case fnv1a("Hello"):
std::cout << "Hello" << std::endl;
break;
default:
break;
}
This case initialized the case values to constants but the call in the switch statement doesn't evaluate to a constexpr and gets ran at run time.
Also equality operators seem to work for some reason so. This example only calls fnv1a once for the dynamic value.
void isValue(const char* str)
{
if (fnv1a(str) == fnv1a("Hello"));
std::cout << "Found it!" << std::endl;
}
I know MSVC has had some issues with compliance, but the behaviour not evaluating to a constant based on the use case rather then if the input is constant just seems odd to me.
The behavior you observe is correct. A constexpr function is required to be called at compile-time on constant expressions only. This includes the cases where the return value of a constexpr function is used as an initializer for constexpr variables, or as the value for a non-type template parameter.
In all other cases, the compiler is not required to evaluate the function at compile-time.

C++11 constexpr function compiler error with ternary conditional operator (?:)

What is wrong with this piece of code?
#include <iostream>
template<unsigned int N, unsigned int P=0>
constexpr unsigned int Log2() {
return (N <= 1) ? P : Log2<N/2,P+1>();
}
int main()
{
std::cout << "Log2(8) = " << Log2<8>() << std::endl;
return 0;
}
When compiling with gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5), I get the following error:
log2.cpp: In function ‘constexpr unsigned int Log2() [with unsigned int N = 0u, unsigned int P = 1023u]’:
log2.cpp:5:38: error: template instantiation depth exceeds maximum of 1024 (use -ftemplate-depth= to increase the maximum) instantiating ‘constexpr unsigned int Log2() [with unsigned int N = 0u, unsigned int P = 1024u]’
log2.cpp:5:38: recursively instantiated from ‘constexpr unsigned int Log2() [with unsigned int N = 4u, unsigned int P = 1u]’
log2.cpp:5:38: instantiated from ‘constexpr unsigned int Log2() [with unsigned int N = 8u, unsigned int P = 0u]’
log2.cpp:10:37: instantiated from here
Constexpr doesn't work that way.
Simply put, constexpr functions must be available as runtime functions too. Imagine you took the constexpr off the function. Then think about why it cannot possibly work.
The reason is that the compiler has to instantiate the body of the function completely; it cannot decide based on the condition in the ?: not to instantiate one side. So it always has to instantiate the recursive call, leading to infinite recursion.
In any case, you're using constexpr wrong. You're using the old template metaprogramming calculation technique (passing stuff as template parameters) when constexpr was intended to replace this. Just use normal parameters.
constexpr unsigned Log2(unsigned n, unsigned p = 0) {
return (n <= 1) ? p : Log2(n / 2, p + 1);
}
std::cout << "Log2(8) = " << Log2(8) << std::endl;
Edit: I'll try to elaborate on how this works.
When the compiler encounters your code, it parses the template function and stores it in template form. (How this works differs between compilers.) So far, all is fine.
Next, in main, the compiler sees the call Log2<8>(). It sees that it has to instantiate the template, so it goes ahead and does exactly that: it instantiates Log2<8, 0>. The body of the function template is this:
return (N <= 1) ? P : Log2<N/2,P+1>();
OK, the compiler sees this, but it doesn't try to evaluate it. Why would it? It's currently instantiating a template, not calculating a value. It just substitutes the values supplied:
return (8 <= 1) ? 0 : Log2<8/2,0+1>();
Huh, there's another template instantiation here. It doesn't matter that it's in a conditional expression, or that the left hand side could be known. Template instantiation must be complete. So it goes ahead and calculates the values for the new instantiation and then instantiates Log2<4, 1>:
return (4 <= 1) ? 1 : Log2<4/2,1+1>();
And the game begins again. There's a template instantiation in there, and it's Log2<2, 2>:
return (2 <= 1) ? 2 : Log2<2/2,2+1>();
And again, Log2<1,3>():
return (1 <= 1) ? 3 : Log2<1/2,3+1>();
Did I mention that the compiler doesn't care about the semantic meaning of this stuff? It's just yet another template to instantiate: Log2<0,4>:
return (0 <= 1) ? 4 : Log2<0/2,4+1>();
And then Log2<0,5>:
return (0 <= 1) ? 5 : Log2<0/2,5+1>();
And so on, and so on. At some point the compiler realizes that it never stops, and gives up. But at no point does it say, "Wait, the condition of that ternary operator is false, I don't need to instantiate the right-hand side." That's because the C++ standard doesn't allow it to. The function body must be instantiated completely.
Now look at my solution. There's no template. There's just a function. The compiler sees it and goes, "Hey, here's a function. Awesome, let me put in a call to that function here." And then at some point (it might be immediately, it might be a lot later, depending on the compiler), it might (but is not forced to, in this case) say, "Hey, wait, this function is constexpr and I know the parameter values, let me evaluate that." Now it goes ahead and evaluates Log2(8, 0). Remember the body:
return (n <= 1) ? p : Log2(n / 2, p + 1);
"OK", the compiler says, "I just want to know what this function returns. Let's see, 8 <= 1 is false, so look at the right side. Log2(4, 1), huh? Let me look at that. OK, 4 <= 1 is also false, so it must be Log2(2, 2). What's that, 2 <= 1? Also false, so it's Log2(1, 3). Hey, 1 <= 1 is true, so let me take that 3 and return it. All the way up the call stack."
So it comes up with the answer 3. It doesn't go into endless recursion because it's evaluating the function with full knowledge of values and semantics, not just stupidly building up ASTs.
I hope that helps.
As others already said: The compiler won't evaluate a conditional expression such as if/else or a ternary operator ?:. However, there is still a way to make this conditional expression compile time:
#include <cstddef> // size_t is shorter than unsigned int, it's a matter of taste in this case
#include <iostream> // to show our results
#include <type_traits> // needed for the mighty std::enable_if
template<size_t N, size_t P = 0>
constexpr typename std::enable_if<(N <= 1), size_t>::type Log2()
{
return P;
}
template<size_t N, size_t P = 0>
constexpr typename std::enable_if<!(N <= 1), size_t>::type Log2()
{
return Log2<N / 2, P + 1>();
}
int main()
{
std::cout << Log2<1>() << "\n";
std::cout << Log2<2>() << "\n";
std::cout << Log2<4>() << "\n";
std::cout << Log2<8>() << "\n";
std::cout << Log2<16>() << "\n";
}
What this does is rather obvious: If N <= 1, the first branch should be evaluated, thus Log2<0, P>() and Log2<1, P>() should evaluate to P. If N <= 1, the upper method is enabled as this function header is valid. For everything else, i.e. N >= 2 or !(N <= 1), we need to recurse, which is done by the second method.