Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial specialization using Concepts

I was just reading the examples of C++20 Concepts. Now I am trying to create a function that will print out if the given type is a hash-table or not using concepts mixed with the partial-specialization. But unfortunately it doesn't work.

#include <iostream>
#include <string>

template<typename T>
concept Hashtable = requires(T a) {
    { std::hash<T>{}(a) } -> std::size_t;
};

struct Foo {};

template <typename T>
void Bar() {
    std::cout << "Type T is not a hashtable" << std::endl;
}

template <Hashtable T>
void Bar<T> {
    std::cout << "Type T is a hashtable" << std::endl;
}

int main()
{
    Bar<Foo>();
    Bar<std::string>();
}

I am using compiler version GCC HEAD 9.0.1, compiler flags are g++ prog.cc -Wall -Wextra -I/opt/wandbox/boost-1.69.0/gcc-head/include -std=gnu++2a "-fconcepts". It gives me following compiler error:

prog.cc:18:6: error: template-id 'Bar<T>' used as a declarator
   18 | void Bar<T> {
      |      ^~~~~~
prog.cc:18:6: error: variable or field 'Bar' declared void
prog.cc:19:54: error: expected '}' before ';' token
   19 |     std::cout << "Type T is a hashtable" << std::endl;
      |                                                      ^
prog.cc:18:13: note: to match this '{'
   18 | void Bar<T> {
      |             ^
prog.cc:20:1: error: expected declaration before '}' token
   20 | }
      | ^

Live Demo

But my expectations were :

Type T is not a hashtable
Type T is a hashtable

My Question

Is it possible to specialize using Concepts?

like image 825
Mohit Avatar asked Jun 13 '26 06:06

Mohit


1 Answers

Function templates cannot be partially specialized (and never could be). Concepts don't change that rule.

However, function templates can be overloaded (and always could be). And concepts do make that easier:

template <typename T>
void Bar() {
    std::cout << "Type T is not a hashtable" << std::endl;
}

template <Hashtable T>
void Bar() {
    std::cout << "Type T is a hashtable" << std::endl;
}

int main()
{
    Bar<Foo>();           // calls the first Bar
    Bar<std::string>();   // calls the second Bar
}

We say the second Bar is more constrained than the first Bar.

like image 121
Barry Avatar answered Jun 16 '26 11:06

Barry



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!