使用概念的部分专业化
Partial specialization using Concepts
我刚刚在阅读 C++20 概念的示例。现在我正在尝试创建一个函数,如果给定类型是散列-table 或不使用与部分专业化混合的概念,该函数将打印出来。但不幸的是它不起作用。
#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 | }
| ^
但我的期望是:
Type T is not a hashtable
Type T is a hashtable
我的问题
是否可以使用概念专业化?
Is it possible to specialize using concepts?
不,不可能对概念进行部分专业化。根据 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).
而且对于函数模板来说,只能重载,不能偏特化。
我用结构特化替换了函数模板特化,我的代码工作正常。看下面的代码。
// 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>();
}
函数模板不能部分特化(而且永远不可能)。概念不会改变这条规则。
但是,函数模板 可以 重载(并且总是可以)。概念 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
更受约束。
我刚刚在阅读 C++20 概念的示例。现在我正在尝试创建一个函数,如果给定类型是散列-table 或不使用与部分专业化混合的概念,该函数将打印出来。但不幸的是它不起作用。
#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 | }
| ^
但我的期望是:
Type T is not a hashtable
Type T is a hashtable
我的问题
是否可以使用概念专业化?
Is it possible to specialize using concepts?
不,不可能对概念进行部分专业化。根据 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).
而且对于函数模板来说,只能重载,不能偏特化。
我用结构特化替换了函数模板特化,我的代码工作正常。看下面的代码。
// 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>();
}
函数模板不能部分特化(而且永远不可能)。概念不会改变这条规则。
但是,函数模板 可以 重载(并且总是可以)。概念 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
更受约束。