概念(Concepts)
在 C++20 中,概念(Concepts)是一種新的語法工具,用於約束模板參數,以提高模板代碼的可讀性和錯誤提示。 概念可以幫助開發者在編譯時期捕捉錯誤,並提供更具體的錯誤信息。 概念是用來定義模板參數所需滿足的條件。 這些條件通常是型別特性、方法簽名或其他編譯時期可檢查的性質。 概念使得模板代碼更加直觀和易於理解,並且可以大大減少模版使用錯誤時的錯誤訊息。
c++ template 是個強大功能,但是缺點就是如果有使用錯誤,錯誤訊息實在又臭又長, 而且根本不知道錯在哪裡..
簡單例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
template<typename T>
T Add(T a, T b)
{
return a + b;
}
class Class1
{
public:
Class1(int value)
{
this->value = value;
}
int value;
};
int main()
{
std::cout << Add(3, 5) << std::endl;
std::cout << Add(3.3, 5.5) << std::endl;
Class1 c1(3);
Class1 c2(5);
std::cout << Add(c1, c2) << std::endl;
return 0;
}
明眼的人就很快看出來 Add(c1, c2) 會錯,因為 Class1 沒有實作 operator+, 這邊要說的是光是這樣簡單的錯誤,錯誤訊息多達 200 多行…
類型形參(Type Parameters)
概念可以用於類型形參,限制泛型類型:
我們先來定義一個整數概念,使用 std::is_integral_v, 簡單來說除了 double 和 float 以外,其餘原生的數字類回傳都是 true.
1
2
template<typename T>
concept Integral = std::is_integral_v<T>;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <concepts>
#include <limits>
template<typename T>
concept Integral = std::is_integral_v<T>;
// 用於類型形參(Type Parameters)
template<Integral T>
class IntegralNumericLimits {
public:
static T min() { return std::numeric_limits<T>::min(); }
static T max() { return std::numeric_limits<T>::max(); }
};
int main() {
std::cout <<" IntegralNumericLimits<bool>::max() : " << IntegralNumericLimits<bool>::max() << std::endl;
std::cout << " IntegralNumericLimits<int>::max() " << IntegralNumericLimits<int>::max() << std::endl;
std::cout << " IntegralNumericLimits<unsigned int>::max() : " << IntegralNumericLimits<unsigned int>::max() << std::endl;
std::cout << " std::numeric_limits<double>::max() : " << std::numeric_limits<double>::max() << std::endl;
return 0;
}
執行結果
帶入 double
1
std::cout << " IntegralNumericLimits::max() : " << IntegralNumericLimits<double>::max() << std::endl;
錯誤資訊明確!!!
requires 表達式
requires 表達式可以用來檢查特定條件是否滿足,例如類型是否有某些成員函數或屬性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <concepts>
template<typename T>
concept Printable = requires(T t) {
{ std::cout << t };
};
class Printer {
public:
void print(Printable auto value) {
std::cout << "Printing: " << value << std::endl;
}
};
int main() {
Printer printer;
printer.print(58); // OK
printer.print("Hello, World!"); // OK
//printer.print(std::vector<int>{1, 2, 3}); // 編譯錯誤,因為 vector 不滿足 Printable
return 0;
}
帶入 vector
1
printer.print(std::vector<int>{1, 2, 3});
編譯錯誤,因為 vector 不滿足 Printable
使用時機
概念適用於以下情境:
- 提高模板代碼的可讀性: 使用概念可以使模板參數的需求更加明確,代碼易於理解。
- 改善錯誤提示: 編譯器可以在編譯時期檢查參數是否滿足概念,並提供更具體的錯誤信息,而不是在使用模板時出現模糊的編譯錯誤。
- 強化代碼約束: 使用概念可以避免在模板中使用不適合的型別,增加代碼的安全性和穩定性。




