Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using C++20 concept/requires for function partial specialization

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!

like image 846
gndrive Avatar asked Oct 23 '25 06:10

gndrive


1 Answers

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.

like image 139
Nicol Bolas Avatar answered Oct 25 '25 21:10

Nicol Bolas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!