![](/img/trans.png)
[英]non-type template parameters, partial specialization vs function argument in C++
[英]Partial template specialization with non-type parameters: GCC vs MSVS
考慮以下簡單的模板專業化:
template<typename T, size_t I>
struct S {};
template<typename T>
struct S<T, std::tuple_size<T>::value> {};
GCC不會編譯它,因為它在模板參數std::tuple_size<T>::value
使用模板參數T
:
錯誤:模板參數'std :: tuple_size <_Tp> :: value'涉及模板參數
現在讓我們用tuple_size
模板參數中的typename std::remove_reference<T>::type
tuple_size
typename std::remove_reference<T>::type
替換T
:
// Using primary structure template from previous example.
template<typename T>
struct S<T, std::tuple_size<typename std::remove_reference<T>::type>::value> {};
該代碼仍在模板參數中使用模板參數,但是GCC對其進行編譯,沒有任何錯誤或警告。 為什么?
現在,如果我們嘗試使用帶有/std:c++latest
標志的MSVS編譯第二個示例,它將以錯誤C2755停止:
部分專業化的非類型參數必須是簡單標識符
這個奇怪的限制是什么? 當I
等於元組大小時,我想停止編譯時遞歸。
那么,誰是錯的:MSVS或GCC?
請注意,即使沒有任何模板實例化,MSVS也會報告錯誤,而GCC在所有這些實例中都能正常工作:
S<std::tuple<int, float>, 9> s1;
S<std::tuple<int, float>, 2> s2;
S<int, 42> s3;
我使用MSVS Community 2015 Update 3及其默認編譯器和GCC 6.2.1。
嘗試了Clang 3.8.0。 它不會用類似於GCC消息的錯誤來編譯兩個片段:
錯誤:非類型模板參數取決於部分專業化的模板參數
在過去的幾年中,該標准中涉及局部類模板專業化可行性的特定部分已多次更改。 [temp.class.spec.match]中的原始限制為:
部分專用的非類型參數表達式不應包含部分專用的模板參數,除非參數表達式是簡單標識符 。
您的代碼顯然與此std::tuple_size<T>::value
, std::tuple_size<T>::value
不是標識符。
然后在cwg問題1315之后將其更改為:
每個模板參數應在非推斷上下文外部的模板ID中至少出現一次。
但是我們沒關系T
在非推導上下文中用作第一個模板參數。 在模板auto
,它現在顯示為:
如果由於其template-parameter-list和template-id的結構而無法推導部分專業化的模板參數 ,則程序格式錯誤。
但是我們也可以。 可以推論得出,您具有正確的“結構”-您的專業化是在與主要對象相同的位置使用非類型模板參數,並且它們應該匹配得很好。
我認為遵循1315號決議(我認為是在 -C ++ 14之后),代碼應該格式正確,但是gcc和clang都拒絕了它。 不幸的解決方法是改為使用兩個類型參數:
template <class T, class I>
struct S;
template<typename T>
struct S<T, typename std::tuple_size<T>::type> {};
template <size_t I>
using size_ = std::integral_constant<size_t, I>;
int main() {
S<std::tuple<int>, size_<1>> s;
}
gcc和clang都接受那個。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.