簡體   English   中英

依賴的非類型參數包:標准說什么?

[英]Dependent non-type parameter packs: what does the standard say?

我認為以下代碼格式正確:

template< typename T >
using IsSigned = std::enable_if_t< std::is_signed_v< T > >;

template< typename T, IsSigned< T >... >
T myAbs( T val );

其他人說它是不正確的,因為C ++ 17標准的§17.7(8.3):

知道哪些名稱是類型名稱允許檢查每個模板的語法。 如果以下情況,該程序格式錯誤,無需診斷:(...) 可變參數模板的每個有效特化都需要空模板參數包 ,或(...)

在我看來, IsSigned< T >...是一個依賴模板參數,因此在模板定義時間內不能根據§17.7(8.3)進行檢查。 IsSigned< T >對於Ts的一個子集可以是void的,對於另一個子集或替換失敗可以是int 對於void子集,確實是空模板參數包是唯一有效的特化,但int子集可以有許多有效的特化。 這取決於實際的T參數。

這意味着編譯器必須在模板實例化后檢查它,因為之前不知道T. 那時完整的參數列表是已知的,零可變參數。 標准說明如下(§17.6.3(7)):

當N為零時,擴展的實例化產生一個空列表。 這樣的實例化不會改變封閉結構的句法解釋

這就是為什么我認為它形成得很好。

  • 你怎么看?
  • 我怎樣才能確定追蹤這種歧義? 很難決定,因為代碼編譯但它沒有任何意義:§17.7(8.3)是NDR,編譯器不必引發任何編譯錯誤。

代碼格式錯誤,無需診斷。

如果std::is_signed_v<T> ,則std::enable_if_t<std::is_signed_v<T>>表示類型void 否則, std::enable_if_t<std::is_signed_v<T>>不表示有效類型。 因此, myAbs每個有效特化myAbs需要一個空模板參數包。

Per [meta.rqmts] / 4 ,如果std::enable_if是專用的,則程序具有未定義的行為。 因此,不能改變上述行為。

在我看來, IsSigned< T >...是一個依賴模板參數,因此在模板定義時間內不能根據§17.7(8.3)進行檢查。 IsSigned< T >對於T s的一個子集可以是void的,對於另一個子集或替換失敗可以是int 對於void子集,確實是空模板參數包是唯一有效的特化,但int子集可以有許多有效的特化。 這取決於實際的T參數。

編譯器無法檢查它,就像它不能為您解決任意方程式一樣。 NDR(無需診斷)完全適用於此類情況 - 程序格式錯誤,如果編譯器實際上能夠檢測到該程序,則需要進行診斷。 NDR允許編譯器不檢查它。

當N為零時,擴展的實例化產生一個空列表。 這樣的實例化不會改變封閉結構的句法解釋。

我們所討論的規則是語義規則,而不是句法規則,因為句法規則在[gram]中。


那么NDR規則的基本原理是什么? 一般而言,它們解決了實施策略中無法重現的問題。 例如,它們可能會導致代碼在某些實現策略中出現異常,但在其他實現策略中不會導致任何問題(並且不容易)。


另外,請注意標准在程序方面與“不良形式”等術語進行對話。 因此,談論孤立的代碼片段的良好形式並不總是合理的。 在這種情況下, std::enable_if不需要專門化,但情況可能會變得更復雜。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM