I come across this problem accidentally.
I have thought google can solve it surely, but after searching multiple keywords, I still can't find answers, which confused me a lot.
When I use prefix at tail position, codes works fine:
template<class ContinerIterator, class F>
constexpr auto fun(ContinerIterator IteratorBegin, ContinerIterator IteratorEnd, F f)
{
switch (IteratorBegin == IteratorEnd)
{
case true: return;
case false: f(*IteratorBegin);
}
return fun(++IteratorBegin, IteratorEnd, f);
}
int main()
{
std::vector<int> a = { 1, 2, 3, 4 };
fun(std::begin(a), std::end(a), [](auto &a)->auto{a *= 2; });
for (auto v : a)
{
std::cout << v << std::endl;
}
return 0;
}
1
2
3
4
Press any key to continue . . .
Howerer, if I use postfix, IteratorBegin
nerve arrives iteratorEnd
and goes far and far away, so segmentfault.
template<class ContinerIterator, class F>
constexpr auto fun(ContinerIterator IteratorBegin, ContinerIterator IteratorEnd, F f)
{
switch (IteratorBegin == IteratorEnd)
{
case true: return;
case false: f(*IteratorBegin);
}
return fun(IteratorBegin++, IteratorEnd, f);
}
void test()
{
}
int main()
{
std::vector<int> a = { 1, 2, 3, 4 };
fun(std::begin(a), std::end(a), [](auto &a)->auto{a *= 2; });
for (auto v : a)
{
std::cout << v << std::endl;
}
return 0;
}
I have tried on MSVC, G++, Clang, all fails. Here is gcc's error list:
Segmentation fault (core dumped)
Here is Clang's:
Error occurred (timeout). Try again later.
This statement
return fun(IteratorBegin++, IteratorEnd, f);
with some exceptions can be considered like
fun(IteratorBegin, IteratorEnd, f);
++IteratorBegin;
return;
So the function is always called with the same value of IteratorBegin
.
From the C++ Standard (5.2.6 Increment and decrement)
1 The value of a postfix ++ expression is the value of its operand. [ Note: the value obtained is a copy of the original value —end note ]...
Consider the following simple program
#include <iostream>
void f(int x)
{
std::cout << "Inside f( x ): x = " << x << std::endl;
}
int main()
{
int x = 0;
std::cout << "Before f( x ): x = " << x << std::endl;
f(x++);
std::cout << "After f( x ): x = " << x << std::endl;
return 0;
}
Its output is
Before f( x ): x = 0
Inside f( x ): x = 0
After f( x ): x = 1
Also it will be useful to consider the following simple program
#include <iostream>
int x = 0;
void f(int x)
{
std::cout << "Local (parameter) x = " << x << std::endl;
std::cout << "Global variable ::x = " << ::x << std::endl;
}
int main()
{
f(x++);
return 0;
}
Its output is
Local (parameter) x = 0
Global variable ::x = 1