摘要訊息 : 一些 C++ 20 引入的小特性.
0. 前言
C++ 20 引入的絕大多數重要特性我們基本都介紹完了, 可以在 Jonny'Blog 中搜尋 C++ 20 閱覽這些文章. 還有一些小特性也是 C++ 20 引入的, 本文文章將通過羅列的方式介紹一部分特性.
1. 名稱查找例外擴展到樣板
在《C++ 學習筆記》中 Code 101 附近, 我們提到了名稱查找中的一個例外情況, 就是當函式參數存在類別的時候, 編碼器還會去這個類別所在的可視範圍之內進行函式匹配. 這個規則本來是不可以用在函式樣板上的, 但是 C++ 20 提案 P0846R0《ADL and Function Templates that are not Visible》將這個規則擴展到了樣板 :
namespace N {
struct A {};
template <typename T>
int f(T);
}
auto x = f(N::A {}); // OK since C++ 20, error before C++ 20
2. 複製建構子中的 const
在 C++ 20 之前, 帶有參數為帶有 const
的複製建構子和不帶有 const
的複製建構子是不相容的 :
struct A {
A(A &);
};
template <typename T>
struct W {
T t;
W(const W &) = default;
};
W<A> w; // Error
C++ 20 提案 P0641R2《Resolving Core Issue #1331 (const
mismatch with defaulted copy constructor)》修正了這個問題, Code 2 在 C++ 20 中可以通過編碼.
3. 樣板存取私用成員
在《【C++】竊取私用成員》中, 我們講述了如何通過樣板來竊取類別的私用成員. 現在這個問題的討論範圍被擴大了, 主要集中在下面的程式碼上 :
template <typename T>
struct traits;
class A {
class B {};
};
template <>
struct traits<A::B> {
// ...
};
根據 C++ 17 標準, 巢狀類別 B
是 A
的私用成員, 所以外部不應該存取到它. 但是如果存取不到它, 一些和 A::B
有關的特性萃取是無法實作的. 因此, GCC 和 MSVC 都允許 Code 3 中的寫法, 而 Clang 則會擲出編碼錯誤. 經過討論之後, C++ 20 提案 P0692R1《Access Checking on Specializations》修改了標準, 允許了 Code 3 中的寫法. 因為這種寫法雖然給予了樣板特殊的存取權限, 但是它並沒有破壞現有代碼的合法性, 特別是在 SFINAE 中, B
仍然是不可訪問的.
4. typename
的省略
C++ 20 提案 P0634R3《Down with typename
!》為 C++ 帶來了幾種可以省略掉 typename
的新地方 :
- 函式的回傳型別, 包括尾置回傳型別;
- 函式的參數列表, 包括函式指標中的參數列表;
using
和typedef
中;- 轉型運算子樣板參數列表部分.
有一種特別的情況,
template <typename T>
void f(int i) {
T::x * i;
}
中的 T::x * i
是表達式, 為 T::x
前增加 typename
宣告反而會引起編碼錯誤.
5. 樣板參數中的類別
C++ 20 提案 P0732R2《Class Types in Non-Type Template Parameters》提出, 讓非型別樣板參數也支援類別. 這些類別必須滿足
- 字面值型別;
- 基礎類別和成員的三路比較運算子 (《【C++ 20】三路比較運算子 (
operator<=>
)》) 回傳的結果為std::strong_ordering
; - 沒有成員被
mutable
或者volatile
標識; - 若存在被
= default
標識的三路比較運算子, 那麼其必須是公有的.
另外, 《C++ 17 特性合集 (二)》第 2 節中提到了 C++ 17 為非型別樣板參數增加了 auto
的推導, 這個推導在 C++ 20 中同樣支援對類別引數的推導.
另一份 C++ 20 提案 P1907R1《Inconsistencies with non-type template parameters》中提出, 既然樣板參數已經支援了類別, 那麼也應該支援指向類別的指標. 因此, C++ 20 的樣板參數中支援放入類別指標或者類別參考.
自創文章, 原著 : Jonny. 如若閣下需要轉發, 在已經授權的情況下請註明本文出處 :