I'm learning C++20 concept/requires. I would like to implement a function for getting the sum of an integer list with template meta programming:
sum<IntList<1, 2, 3>>();
As it's known that C++ standards don't allow function partial specialization, I would like to use C++20 concept/requires to the similar stuff as function partial specialization.
Here is my code:
#include <iostream>
template<int...N>
class IntList;
template<int...N>
concept IsIntList = IntList<N...>{};
template<typename T>
int sum() {
return 0;
}
template<int...N>
requires IsIntList<N...>
int sum() {
return (N + ...);
}
int main() {
std::cout << sum<IntList<1, 2>>() << std::endl;
return 0;
}
But it could not produce what I want. Put my code in C++ Insights. The first sum is instantiated, instead of the second sum.
Here is the result of C++Insights:
#include <iostream>
template<int...N>
class IntList;
template<int...N>
concept IsIntList = IntList<N...>{};
template<typename T>
int sum() {
return 0;
}
/* First instantiated from: insights.cpp:21 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
int sum<IntList<1, 2> >()
{
return 0;
}
#endif
template<int...N>
requires IsIntList<N...>
int sum() {
return (N + ...);
}
int main()
{
std::cout.operator<<(sum<IntList<1, 2> >()).operator<<(std::endl);
return 0;
}
What's the correct way to solve this problem? Thanks!
The central problem you're encountering is that you have a type template parameter whose type you want to be constrained to being some specialization of some template. That's not a thing you can do with a requires clause. At least, not easily.
It's best to avoid this problem. You're only encountering it because you insist that sum's template parameter must be some specialization of IntList instead of the integers themselves directly. The best way to handle this is by ditching this assumption:
template<int... Ints>
constexpr int sum(IntList<Ints...>)
{ return (0 + ... + Ints); }
You then call this function as so: sum(IntList<1, 2>{}). Note that IntList needs to have a constexpr default constructor.
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