考虑以下代码(也可以在编译器资源管理器中找到)
#include <utility>
#include <type_traits>
template <std::size_t N, class = std::make_index_sequence<N>>
struct type;
template <std::size_t N, std::size_t... I>
struct type<N, std::index_sequence<I...>>
: std::integral_constant<std::size_t, I>... {
using std::integral_constant<std::size_t, I>::operator()...;
};
using x = type<4>;
对于许多编译器,它会导致编译错误:
// icc 19.0.0: <source>(10): error: parameter pack "I" was referenced but not expanded
// icc 19.0.1: OK
// gcc 6.4: <source>:10:60: error: parameter packs not expanded with '...'
// gcc 7.1: OK
// clang 3.9.1: <source>:10:11: error: using declaration contains unexpanded parameter pack 'I'
// clang 4.0.0: OK
// msvc 19.22: <source>(10): error C3520: 'I': parameter pack must be expanded in this context
// msvc 19.23: OK
对我来说,这似乎是完全有效的c++17
代码,但我很惊讶,它似乎不编译相对较新的编译器(特别是intel
和msvc
)(即使它编译在所有最新的版本)。
我想知道是否:
- 这是完全
c++17
有效的代码,它只是花了很长时间为一些供应商实现它 - 不是纯
c++17
有效代码
我想知道是否:
- 它完全是c++17的有效代码,只是一些供应商花了很长时间来实现它
- 它不是纯粹的c++17有效代码
代码是有效的,但是你列出的编译器版本要么很旧,还不支持这个特定的特性,要么声称支持这个特性,但包含一个错误。
一般来说,一定要了解特定编译器的特定版本的限制。对于像上面的例子那样被诊断为格式不良的程序,主要是像下面这样的检测练习,但是使用旧的编译器版本可能会有更糟糕的后果:编译器或c++语言缺陷,这些缺陷只有在以后的编译器版本中才能解决。
详情见下文
c++ 17的哪个特性是"罪魁祸首"?
using std::integral_constant<std::size_t, I>::operator()...;
这是using声明中的包扩展,在c++ 17中包含为:
- P0195R2: using-declarations 中的包扩展
各种编译器对c++ 17标准的支持
GCC// gcc 6.4: <source>:10:60: error: parameter packs not expanded with '...' // gcc 7.1: OK
从GCC中的c++标准支持到GCC中的c++ 17支持:
- P0195R2为GCC 7实现。
因此,预计您的程序将无法在GCC 6.4中编译,因为该特性尚未在该GCC版本中实现。
叮当声
// clang 3.9.1: <source>:10:11: error: using declaration contains unexpanded parameter pack 'I' // clang 4.0.0: OK
来自Clang中的c++支持- c++ 17实现状态:
- P0195R2在Clang 4中实现。
因此,如上所述,我们不能期望您的程序能够为Clang <4 .
MSVC
// msvc 19.22: <source>(10): error C3520: 'I': parameter pack must be expanded in this context // msvc 19.23: OK
来自Microsoft C/c++语言一致性的Visual Studio版本:
- P0195R2据称已在VS 2017 15.7中(完全)实现。
但是MSVC 19.22无法编译你的程序是一个bug:
- 可变模板:无效的参数包上下文
在VS16.3/MSVC 19.23中被标记为已修复