Use C++20 Concept to constrain template parameter

Viewed 449

I want to use concepts to replace a design which currently uses SFINAE (enable_if). To simplify, I have created a simpler example which shows an identical problem:

template<typename T>
concept smallerThanPointer = sizeof(T) < sizeof(void*);

template<typename T>
concept notSmallerThanPointer = !smallerThanPointer<T>;


template<smallerThanPointer T>
class MyClass
{
 public:
    MyClass() { std::cout << "MyClass[smallerThanPointer]\n"; }
};

template<notSmallerThanPointer T>
class MyClass
{
 public:
    MyClass() { std::cout << "MyClass[...]\n"; }
};


int main()
{
    MyClass<int[8]> c1;

    return 0;
}

But my compiler (g++-11) will not accept this syntax because it thinks I'm redeclaring MyClass. Also this example is not possible:

template<typename T>
class MyClass requires smallerThanPointer<T>
{
 public:
    MyClass() { std::cout << "MyClass[smallerThanPointer]\n"; }
};

template<typename T>
class MyClass
{
 public:
    MyClass() { std::cout << "MyClass[...]\n"; }
};

All examples I have found online with concepts only discuss how to apply concepts to function parameters. So is it possible at all to do with a class?

1 Answers

The correct syntax for the partial template specialization for constraints should be:

template<typename T>
concept smallerThanPointer = sizeof(T) < sizeof(void*);
    
template<class T>
class MyClass
{
public:
    MyClass() { std::cout << "MyClass[...]\n"; }
};
    
template<class T> requires smallerThanPointer<T>
class MyClass<T>
{
public:
    MyClass() { std::cout << "MyClass[smallerThanPointer]\n"; }
};

Demo.

Related