Consider the following code (also available here on compiler explorer)
#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>;
For many compilers, it leads to a compiler error:
// 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
To me, it seems like perfectly valid c++17
code but I am surprised that it does not seem to compile on relatively recent compilers (especially for intel
and msvc
) (even if it compiles on all the most recent versions).
I am wondering whether:
c++17
valid code and it just took a long time for some vendors to implement itc++17
valid codeI 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
The code is valid but the compiler version you are listing are either very old and did not yet support this particular feature, or claimed to support this feature but contained a bug.
In general, make sure to understand the limitations of the particular version of your particular compiler. For programs diagnosed as ill-formed as the example above, it is mostly a detective exercise such as the one following below, but using old compiler versions can have far worse consequences: compiler or C++ language defects that have only been addressed in later versions of the compiler.
See details below.
using std::integral_constant<std::size_t, I>::operator()...;
This is a pack expansion in a using-declaration, which was included in C++17 as:
// gcc 6.4: <source>:10:60: error: parameter packs not expanded with '...' // gcc 7.1: OK
From C++ Standards Support in GCC - C++17 Support in GCC:
Thus, it is expected that your program will not compile for GCC 6.4, as feature was not yet implemented in that GCC version.
// clang 3.9.1: <source>:10:11: error: using declaration contains unexpanded parameter pack 'I' // clang 4.0.0: OK
From C++ Support in Clang - C++17 implementation status:
Thus, as above, we cannot expect your program to compile for Clang < 4.
// msvc 19.22: <source>(10): error C3520: 'I': parameter pack must be expanded in this context // msvc 19.23: OK
From Microsoft C/C++ language conformance by Visual Studio version:
However the failure of MSVC 19.22 to compile your program is a bug:
Flagged to have been fixed in VS16.3/MSVC 19.23