Let us consider the following example source in C++:
template <class begin, class... end>struct test { template <end... beg_vals, begin end_val> static consteval void make() { }};int main() { test<char, int, float>::make<4, 6.f, 'a'>();}
Parameter packs can not be placed at the beginning of a template declaration, but here beg_vals
just expand a pack (at least thought so). I thought this program is valid, although is does not compile with either gcc
or msvc
.
gcc
's error message:
<source>: In function 'int main()':<source>:9:46: error: no matching function for call to 'test<char, int, float>::make<4, 6.0e+0f, 'a'>()' 9 | test<char, int, float>::make<4, 6.f, 'a'>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~<source>:4:27: note: candidate: 'template<end ...beg_vals, char end_val> static consteval void test<begin, end>::make() [with end ...beg_vals = {beg_vals ...}; begin end_val = end_val; begin = char; end = {int, float}]' 4 | static consteval void make() { | ^~~~<source>:4:27: note: template argument deduction/substitution failed:<source>:9:46: error: conversion from 'float' to 'char' in a converted constant expression 9 | test<char, int, float>::make<4, 6.f, 'a'>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~<source>:9:46: error: could not convert '6.0e+0f' from 'float' to 'char' 9 | test<char, int, float>::make<4, 6.f, 'a'>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~ | | | float<source>:9:46: error: wrong number of template arguments (3, should be 2)<source>:4:27: note: provided for 'template<end ...beg_vals, char end_val> static consteval void test<begin, end>::make() [with end ...beg_vals = {beg_vals ...}; begin end_val = end_val; begin = char; end = {int, float}]' 4 | static consteval void make() { | ^~~~Compiler returned: 1
msvc
's error message:
example.cpp<source>(4): error C3547: template parameter 'end_val' cannot be used because it follows a template parameter pack and cannot be deduced from the function parameters of 'test<begin,end...>::make'<source>(3): note: see declaration of 'end_val'<source>(4): note: the template instantiation context (the oldest one first) is<source>(2): note: while compiling class template 'test'Compiler returned: 2
At the same time, the program is accepted by modern clang++
.
I continued my experiment swapping beginning...
and end
parameter in make()
:
template <class begin, class... end>struct test { template <begin end_val, end... beg_vals> static consteval void make() { }};int main() { test<char, int, float>::make<'a', 4, 6.f>();}
This made msvc
to accept the code.
gcc
's error message changed, but it continued to "expect two template parameters" in make.
I am pretty sure that gcc
is at least wrong at its error message.
My questions are:
- Is the first source valid?
- Is the second source valid?
- Is there a bug report for
gcc
?
Additionally: