在多年的模板元編程實踐中,我遇到了各種奇怪的編譯器錯誤和錯誤。但是對于這個,我必須說我有些困惑。我不知道哪個編譯器是正確的:gcc, clang, msvc, 并且intel都給出不同的結果(盡管聽起來令人驚訝,但只能intel編譯沒有錯誤的代碼)。更令人驚訝的是,它不依賴任何新C 功能,因為它只是C 11涉及。
代碼會自己說話,因為它相對簡單。它只包含一個可變引數模板模板包裝器和一個可變引數內部物體,該物體可以是結構或別名模板。無論出于何種原因,別名模板版本在構造它的實體時會為某些編譯器回傳錯誤:
#include <type_traits>
template <class T1, class T2, class T3>
struct ternary {};
template <template <class...> class Template, class... Types>
struct template_struct {
template <class... Args>
struct type: Template<Types..., Args...> {};
};
template <template <class...> class Template, class... Types>
struct template_alias {
template <class... Args>
using type = Template<Types..., Args...>;
};
現在測驗:
int main(int, char**) {
using ts0 = template_struct<ternary>; // OK
using ts1 = template_struct<ternary, bool>; // OK
using ts2 = template_struct<ternary, bool, char>; // OK
using ts3 = template_struct<ternary, bool, char, int>; // OK
using ts4 = template_struct<ternary, bool, char, int, double>; // OK
ts0 s0; // OK
ts1 s1; // OK
ts2 s2; // OK
ts3 s3; // OK
ts4 s4; // OK
using ta0 = template_alias<ternary>; // OK
using ta1 = template_alias<ternary, bool>; // OK
using ta2 = template_alias<ternary, bool, char>; // OK
using ta3 = template_alias<ternary, bool, char, int>; // OK
using ta4 = template_alias<ternary, bool, char, int, double>; // OK
ta0 a0; // OK
ta1 a1; // OK
ta2 a2; // OK
ta3 a3; // GCC, INTEL => OK | CLANG, MSVC => ERROR: WAIT WHAT ?!?!
ta4 a4; // INTEL => OK | GCC, CLANG, MSVC => ERROR
return 0;
}
該代碼可在編譯器資源管理器中找到:https ://godbolt.org/z/3ndYMWvfs
問題:發生了什么?哪個編譯器是正確的?標準是怎么說的?它是編譯器錯誤嗎?
uj5u.com熱心網友回復:
所有編譯器都是正確的,兩個失敗的測驗是格式錯誤的 NDR(“不需要診斷”)。
論據案例是格式錯誤的> 3NDR,因為[temp.res.general]/6.1:
該程式格式錯誤,不需要診斷,如果:
— 不能為模板生成有效的特化......并且模板沒有被實體化,......
論據案例是格式錯誤的== 3NDR,因為[temp.res.general]/6.3:
該程式格式錯誤,不需要診斷,如果:
— 可變引數模板的每個有效特化都需要一個空模板引數包...
這兩個template_struct<ternary, ...>測驗似乎是合法的,因為您可以將其專門struct type化為有效的東西,而且我沒有立即看到必須至少有一個主要(非專門化)模板的有效專門化的規則。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/472203.html
