参数包在 using 声明中被引用但未扩展:是否存在编译器错误?
Parameter pack referenced but not expanded in a using declaration: compiler bugs or not?
考虑以下代码(在编译器资源管理器上也可用 here)
#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
有效代码
I am wondering whether:
- it's completely c++17 valid code and it just took a long time for some vendors to implement it
- it is not purely c++17 valid code
代码有效,但您列出的编译器版本太旧且尚不支持此特定功能,或者声称支持此功能但包含错误。
一般来说,请务必了解您的特定编译器的特定版本的限制。对于如上例诊断为 ill-formed 的程序,它主要是一个侦探练习,如下面的一个,但使用旧的编译器版本可能会产生更糟糕的后果:编译器或 C++ 语言缺陷仅在以后的版本中得到解决编译器的版本。
查看下面的详细信息。
什么特定的 C++17 特性是“罪魁祸首”?
using std::integral_constant<std::size_t, I>::operator()...;
这是 using-declaration 中的包扩展,它包含在 C++17 中,如下所示:
- P0195R2:在 using-declarations
内打包扩展
各种编译器对 C++17 标准的支持
海湾合作委员会
// gcc 6.4: <source>:10:60: error: parameter packs not expanded with '...'
// gcc 7.1: OK
来自 C++ Standards Support in GCC - C++17 Support in GCC:
- 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
来自C++ Support in Clang - C++17 implementation status:
- 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++ language conformance by Visual Studio version:
- P0195R2 声称已经(完全)实现了 VS 2017 15.7。
但是 MSVC 19.22 无法编译您的程序是一个错误:
标记为已在 VS16.3/MSVC 19.23 中修复
考虑以下代码(在编译器资源管理器上也可用 here)
#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
有效代码
I am wondering whether:
- it's completely c++17 valid code and it just took a long time for some vendors to implement it
- it is not purely c++17 valid code
代码有效,但您列出的编译器版本太旧且尚不支持此特定功能,或者声称支持此功能但包含错误。
一般来说,请务必了解您的特定编译器的特定版本的限制。对于如上例诊断为 ill-formed 的程序,它主要是一个侦探练习,如下面的一个,但使用旧的编译器版本可能会产生更糟糕的后果:编译器或 C++ 语言缺陷仅在以后的版本中得到解决编译器的版本。
查看下面的详细信息。
什么特定的 C++17 特性是“罪魁祸首”?
using std::integral_constant<std::size_t, I>::operator()...;
这是 using-declaration 中的包扩展,它包含在 C++17 中,如下所示:
- P0195R2:在 using-declarations 内打包扩展
各种编译器对 C++17 标准的支持
海湾合作委员会
// gcc 6.4: <source>:10:60: error: parameter packs not expanded with '...' // gcc 7.1: OK
来自 C++ Standards Support in GCC - C++17 Support in GCC:
- 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
来自C++ Support in Clang - C++17 implementation status:
- 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++ language conformance by Visual Studio version:
- P0195R2 声称已经(完全)实现了 VS 2017 15.7。
但是 MSVC 19.22 无法编译您的程序是一个错误:
标记为已在 VS16.3/MSVC 19.23 中修复