簡體   English   中英

具有非類型參數的部分模板專業化:GCC與MSVS

[英]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>::valuestd::tuple_size<T>::value不是標識符。

然后在cwg問題1315之后將其更改為:

每個模板參數應在非推斷上下文外部的模板ID中至少出現一次。

但是我們沒關系T在非推導上下文中用作第一個模板參數。 模板auto ,它現在顯示為:

如果由於其template-parameter-listtemplate-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.

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