使用概念进行部分专业化

时间:2019-03-19 05:14:06

标签: c++ partial-specialization c++-concepts c++20

我只是在阅读C ++ 20概念的示例。现在,我正在尝试创建一个函数,该函数将在给定类型为哈希表或不使用与部分专业化混合的概念时将其打印出来。但不幸的是,它不起作用。

#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

我的问题

是否可以使用Concepts进行专门研究?

3 个答案:

答案 0 :(得分:3)

功能模板不能部分专门化(而且永远不能如此)。概念不会改变该规则。

但是,功能模板 可以重载(并且总是可以)。而的概念使这变得更容易:

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受约束。

答案 1 :(得分:2)

我已经用结构专用化替换了功能模板专用化,并且我的代码运行良好。看下面的代码。

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

答案 2 :(得分:1)

  

是否可以专门使用概念?

否,不可能部分专门化概念。根据{{​​3}}上的在线参考:

  

不允许概念的显式实例化,显式专业化,或部分专业化(约束原始定义的含义不能更改)。

就功能模板而言,它们只能重载,而不能部分地专门化。