Частичная специализация с использованием концепций - PullRequest
0 голосов
/ 19 марта 2019

Я только что читал примеры C ++ 20 Concepts.Теперь я пытаюсь создать функцию, которая будет распечатывать, если данный тип является хеш-таблицей или не использует понятия, смешанные с частичной специализацией.Но, к сожалению, это не работает.

#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>();
}

Я использую версию компилятора GCC HEAD 9.0.1, флаги компилятора g++ prog.cc -Wall -Wextra -I/opt/wandbox/boost-1.69.0/gcc-head/include -std=gnu++2a "-fconcepts".Это дает мне следующую ошибку компилятора:

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

Но мои ожидания были:

Type T is not a hashtable
Type T is a hashtable

Мой вопрос

Можно ли специализироваться с помощью концепций?

Ответы [ 3 ]

3 голосов
/ 19 марта 2019

Шаблоны функций не могут быть частично специализированными (и никогда не могут быть). Концепции не меняют это правило.

Однако шаблоны функций могут быть перегружены (и всегда могут быть). А концепции do делают это проще:

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
}

Мы говорим, что второй Bar на более ограничен , чем первый Bar.

2 голосов
/ 19 марта 2019

Я заменил специализацию шаблона функции специализацией Struct, и мой код работает нормально.Посмотрите на следующий код.

// 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>();
}
1 голос
/ 19 марта 2019

Можно ли специализироваться, используя понятия?

Нет, невозможно частично специализировать понятия. Согласно онлайн-справке на Ограничения и концепции :

Явные экземпляры, явные специализации, или частичные специализации понятий не допускаются (значение исходного определения ограничения изменить нельзя).

А что касается шаблонов функций, они могут быть перегружены, но не частично специализированы.

...