6

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?

P.W
  • 26,289
  • 6
  • 39
  • 76
Mohit
  • 1,225
  • 11
  • 28

3 Answers3

8

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.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • The code that follows the statement, "And concepts *do* make that easier:" is not quite demonstrative of how *concepts* make it easier. – P.W Mar 20 '19 at 04:35
  • 1
    @P.W. Try writing those two function template overloads without concepts. – Barry Mar 20 '19 at 12:21
  • @moyang_mm [Yes, it does](https://godbolt.org/z/ez1vPe). If it doesn't, it's a compiler error. – Barry Nov 15 '20 at 11:16
5

I've replaced the function template specialization with structs specialization and my code is working fine. Look at the following code.

// This file is a "Hello, world!" in C++ language by GCC for wandbox.
#include <iostream>
#include <string>

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

struct Foo {};

template <typename T>
struct Boo {
    static constexpr char value[] = "Type T is not a hashtable";
};

template <Hashtable HashT>
struct Boo<HashT> {
    static constexpr char value[] = "Type T is a hashtable";
};

template <typename T>
void Bar() {
    std::cout << Boo<T>::value << std::endl;
}

int main()
{
    Bar<int>();
    Bar<Foo>();
}
Mohit
  • 1,225
  • 11
  • 28
0

Is it possible to specialize using concepts?

No, it is not possible to partially specialize concepts. As per the online reference on Constraints and concepts:

Explicit instantiations, explicit specializations, or partial specializations of concepts are not allowed (the meaning of the original definition of a constraint cannot be changed).

And as far as function templates are concerned, they can only be overloaded, not partially specialized.

P.W
  • 26,289
  • 6
  • 39
  • 76
  • Not sure why this is being downvoted - but it's worth pointing out that the question is about specializing using concepts but you're answering about specializing concepts. That's a correct answer - but it's not really what's being asked? – Barry Mar 19 '19 at 17:02
  • This doesn't answer the question, which is about using concepts for the purposes of specialization, not whether concepts themselves can be specialized. – cigien Aug 23 '21 at 01:22