![](/img/trans.png)
[英]Partial template specialization for partial template parameter application not working GCC 4.8.1
[英]GCC/CLang disagree on partial specialization of template template parameter
GCC和clang對此代碼持不同意見。
#include <type_traits>
template <typename T, template <typename...> typename Tpl>
struct storage {
using type_t = T;
template <typename... Args>
using storage_tpl = Tpl<Args...>;
};
template <typename T, template <typename...> typename>
struct F{
constexpr static int x = 1;
};
template <typename T >
struct F<T, std::void_t>{
constexpr static int x = 2;
};
int f() {
using S = storage<int, std::void_t>;
static_assert(F<int, S::storage_tpl>().x == 2);
return F<int, S::storage_tpl>().x;
}
根據clang S::storage_tpl
不是std::void_t
; 結果,它選擇主模板F而不是部分特化,從而選擇斷言。
乍一看,看起來GCC是正確的,因為它理解嵌套模板只是std::void_t
的別名,但也許它太聰明了,標准要求S::storage_tpl
和std::void_t
必須是兩個不同的模板。
誰是對的?
目前看來這是未指定的,而且對於TC而言,它看起來像CWG缺陷報告1286所述,其中說:
通過更改17.5 [temp.type]第1段中的示例解決了問題1244
template<template<class> class TT> struct X { }; template<class> struct Y { }; template<class T> using Z = Y<T>; X<Y> y; X<Z> z;
至
template<class T> struct X { }; template<class> struct Y { }; template<class T> using Z = Y<T>; X<Y<int> > y; X<Z<int> > z;
事實上,最初的意圖是該例子應該是正確的; 然而,缺少這樣做的規范性措辭。 17.6.7 [temp.alias]的當前措辭僅涉及別名模板的特化與替換后的type-id的等價性。 需要添加措辭,指定別名模板本身在何種情況下等同於類模板。
並提出以下決議:
在17.6.7 [temp.alias]第2段之后添加以下新段落:
當別名模板聲明中的type-id(稱為A)由一個simple-template-id組成時,其中template-argument-list由一個標識符列表組成,這些標識符將A的每個模板參數命名為恰好一次它們出現在A的template-parameter-list中的順序,如果A和T具有相同數量的模板參數,則別名模板等同於simple-template-id中命名的模板(稱為T)。 [腳注: 此規則具有傳遞性:如果別名模板A等同於另一個等同於模板C的別名模板B,則A也等同於C,A和B也相互等效 。 - 尾注] [例子:
template<typename T, U = T> struct A; template<typename V, typename W> using B = A<V, W>; // equivalent to A template<typename V, typename W> using C = A<V>; // not equivalent to A: // not all parameters used template<typename V> using D = A<V>; // not equivalent to A: // different number of parameters template<typename V, typename W> using E = A<W, V>; // not equivalent to A: // template-arguments in wrong order template<typename V, typename W = int> using F = A<V, W>; // equivalent to A: // default arguments not considered template<typename V, typename W> using G = A<V, W>; // equivalent to A and B template<typename V, typename W> using H = E<V, W>; // equivalent to E template<typename V, typename W> using I = A<V, typename W::type>; // not equivalent to A: // argument not identifier
- 末端的例子]
但是此解決方案存在問題,缺陷報告仍然有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.