簡體   English   中英

別名模板的包擴展

[英]Pack expansion for alias template

似乎包參數只能在別名模板的包參數的位置進行擴展。 對於類或函數模板,情況並非如此:

template <class T, class... Args> struct x { using type = T; };

template <class T, class... Args> using x_t     = typename x<T, Args...>::type;
template <class... Args>          using x_fix_t = typename x<Args...>::type;

template <class... Args> auto f(Args...) -> void {
  typename x<Args...>::type v1; // OK
  x_t<Args...> v2; // Error
  x_fix_t<Args...> v3; // OK
}

更簡單的情況:

template <class T, class U> using y_t = T;

template <class... Args> auto f(Args...) -> void {
  y_t<Args...> v4; // Error
}

上面的代碼在g++ 4.9g++ 5.1clang 3.5使用c++11c++14都會產生錯誤(即使f從未實例化)。

為什么不允許這樣做,一般規則是什么? 我認為沒有理由限制這一點。 這似乎是一個很奇怪的禁令。

至於為什么不用第一個變體寫為x_fix_t更清楚的是x_t有一個強制性的第一個參數。 (例如,這就是不允許f()的原因)。 但這並不重要,修復很容易。 問題仍然存在:為什么?

gcc 錯誤:

error: pack expansion argument for non-pack parameter ‘T’ of
alias template ‘template<class T, class ... Args> using x_t = typename x::type’

叮當錯誤:

error: pack expansion used as argument for non-pack parameter of
alias template   x_t<Args...> v2;

這在 GCC 4.8 中編譯但在 GCC 4.9 中失敗,這證明它與 CWG 1430 和錯誤報告 #59498 相關 Roy Chrihfield 提出的修復方法與您的完全相同:

Rewriting the code to use a struct succeeds:

template <typename T, typename ...>
struct alias { using type = T; };

template <typename ...T>
using variadic_alias = typename alias<T...>::type;

此外,Jason Merrill 詳細說明了為什么它會失敗:

實際上,不,這很大程度上是 Core 1430 的問題; 沒有辦法修改 variadic_alias<T...> 而不在修改中提到別名模板的名稱,它們應該是完全透明的。 這僅在 4.8 中偶然有效,因為該版本禁用了檢查。

錯誤報告中沒有進一步的討論,所以我們可以轉向 CWG 1430:

最初,包擴展不能擴展為固定長度的模板參數列表,但在 N2555 中更改了這一點。 這適用於大多數模板,但會導致別名模板出現問題。

在大多數情況下,別名模板是透明的; 當它在模板中使用時,我們可以只替換依賴模板參數。 但是,如果模板 id 對非可變參數使用包擴展,則這不起作用。 例如:

 template<class T, class U, class V> struct S {}; template<class T, class V> using A = S<T, int, V>; template<class... Ts> void foo(A<Ts...>);

沒有辦法用 S 來表達 A<Ts...>,所以我們需要保持 A,直到我們有 Ts 來替代,因此它需要在 mangling 中處理。

目前,EDG 和 Clang 拒絕了這個測試用例,抱怨 A.G++ 的模板參數太少,但我認為這是一個錯誤。 但是,在 ABI 列表中,John Spicer 認為應該拒絕它。

(另見第 1558 期。)

2012 年 10 月會議記錄:

CWG 的共識是這種用法應該被禁止,當依賴參數不能簡單地直接替換到 type-id 時,不允許使用別名模板。

補充說明,2013 年 4 月:

再舉一個例子,考慮:

 template<class... x> class list{}; template<class a, class... b> using tail=list<b...>; template <class...T> void f(tail<T...>); int main() { f<int,int>({}); }

在處理此示例時存在實現差異。

換句話說,這是一個持續存在的問題,看不到任何解決方案 (AFAIC)。

暫無
暫無

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

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