#include <iostream>
#include <utility>
template<std::size_t... items>
constexpr std::size_t count()
{
return std::index_sequence<items...>().size();
}
template<std::size_t... items>
constexpr std::size_t fold_mul()
{
if( count<items...>() == 0 )
{
return 1;
}
else
{
return (... * items);
}
}
int main()
{
std::cout << "Result: " << fold_mul<>() << "\n";
}
This code is expected to output 1
but instead throws the error:
<source>:19:28: error: fold of empty expansion over operator*
19 | return (... * items);
My question is: Why doesn't this work, as the fold_expression is clearly in the else
part.
For reference, this implementation works:
template<typename... Args>
constexpr std::size_t fold_mul();
template<std::size_t... j>
requires (count<j...>() > 0)
constexpr std::size_t fold_mul()
{
return (j * ...);
}
template<>
constexpr std::size_t fold_mul()
{
return 1;
}
The problem is, when being specified fold expression with empty expansion, (... * items)
is invalid at compile-time; even it won't be evaluated at run-time.
You can use constexpr if (since C++17); then the else-part will be discarded when being specified fold expression with empty expansion.
If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.
template<std::size_t... items>
constexpr std::size_t count()
{
return std::index_sequence<items...>().size();
}
template<std::size_t... items>
constexpr std::size_t fold_mul()
{
if constexpr ( count<items...>() == 0 )
// ^^^^^^^^^
{
return 1;
}
else
{
return (... * items);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With