2

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?

alexpanter
  • 1,222
  • 10
  • 25
  • 1
    `requires` can go immediately after the template parameter list; for functions only, it can also go after the (ordinary) parameter list because it’s sometimes easier to phrase constraints in terms of parameters. – Davis Herring Sep 26 '21 at 17:38

1 Answers1

4

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.

alexpanter
  • 1,222
  • 10
  • 25
康桓瑋
  • 33,481
  • 5
  • 40
  • 90