参数包在 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 代码,但令我惊讶的是它似乎无法在相对较新的编译器上编译(尤其是对于 intelmsvc)(即使它在所有最新版本上编译。

我想知道是否:

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 中修复