https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114446
Bug ID: 114446 Summary: Spurious "inconsistent parameter pack deduction" error when constraining template function Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: gccbugzilla at maycontaincode dot com Target Milestone: --- Created attachment 57790 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=57790&action=edit Minimal C++ source file that reproduces the issue I have a file "bug.cpp", a 24-line C++ source file that does not include any headers, its full content is at the bottom of this description. Within, there are two template functions that each take a typename, a parameter pack of types deduced from the function arguments, and a non-type template parameter with default value. One of them uses an enable_if construct for the nontype template argument to constrain based on the first template argument, but in this file it never causes SFINAE (which is correct). I try a few methods of calling these functions, each time passing the same two template arguments and the same one function argument. The behavior that seems incorrect to me is that GCC apparently gives different treatment for the template function that is constrained unless the function argument is casted to the type it would have been implicitly converted to anyway. The unconstrained template doesn't care that the function parameter doesn't exactly match the explicitly-specified template parameter, it happily performs the implicit conversion. Everything else is the same so I do not understand what could be causing this behavior. I also tried replacing the enable_if construct with a template using alias that doesn't constrain, and GCC accepts that without error, so it seems like the issue only happens when using template class partial specialization. I am unable to reproduce the issue in MSVC 14.40.33617 or Clang 18.1.0, they both accept "bug.cpp" without incident. I did some searching through other bug reports, but could not find anything that looked related, and searching the exact error message in summary-only mode actually gave me zero results. Output of gcc -v: > Using built-in specs. > COLLECT_GCC=gcc > COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/12/lto-wrapper > OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa > OFFLOAD_TARGET_DEFAULT=1 > Target: x86_64-linux-gnu > Configured with: ../src/configure -v --with-pkgversion='Debian 12.2.0-14' > --with-bugurl=file:///usr/share/doc/gcc-12/README.Bugs > --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr > --with-gcc-major-version-only --program-suffix=-12 > --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id > --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix > --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug > --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new > --enable-gnu-unique-object --disable-vtable-verify --enable-plugin > --enable-default-pie --with-system-zlib --enable-libphobos-checking=release > --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch > --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 > --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic > --enable-offload-targets=nvptx-none=/build/gcc-12-bTRWOB/gcc-12-12.2.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-12-bTRWOB/gcc-12-12.2.0/debian/tmp-gcn/usr > --enable-offload-defaulted --without-cuda-driver --enable-checking=release > --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu > Thread model: posix > Supported LTO compression algorithms: zlib zstd > gcc version 12.2.0 (Debian 12.2.0-14) I have also used Compiler Explorer to try "x86-64 gcc 5.1", "x86-64 gcc 13.2" and "x86-64 gcc (trunk)", all three produce the same issue as my local GCC version: https://gcc.godbolt.org/z/9b6faWanW Command line that produces the issue: > g++ -std=c++17 bug.cpp Output of above command: > bug.cpp: In function ‘void runtest2b()’: > bug.cpp:22:25: error: no matching function for call to ‘test2<int, > int*>(std::nullptr_t)’ > 22 | test2<int, int*>(nullptr); //3 > | ~~~~~~~~~~~~~~~~^~~~~~~~~ > bug.cpp:11:6: note: candidate: ‘template<class T, class ... Args, typename > enable_if_not_void<T, int>::type <anonymous> > void test2(Args&& ...)’ > 11 | void test2(Args&&...){} > | ^~~~~ > bug.cpp:11:6: note: template argument deduction/substitution failed: > bug.cpp:22:25: note: inconsistent parameter pack deduction with ‘int*’ and > ‘std::nullptr_t’ > 22 | test2<int, int*>(nullptr); //3 > | ~~~~~~~~~~~~~~~~^~~~~~~~~ Adding -save-temps to the command line generates a file "a-bug.ii" with this content, which is identical to the "bug.cpp" file after the first several lines, other than omitting irrelevant comments: # 0 "bug.cpp" # 0 "<built-in>" # 0 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 0 "<command-line>" 2 # 1 "bug.cpp" template<typename, typename T> struct enable_if_not_void { using type = T; }; template<typename T> struct enable_if_not_void<void, T> {}; template<typename V, typename T> using enable_if_not_void_t = typename enable_if_not_void<V, T>::type; template<typename T, typename... Args, int = 0> void test1(Args&&...){} template<typename T, typename... Args, enable_if_not_void_t<T, int> = 0> void test2(Args&&...){} void runtest1() { test1<int, int*>(nullptr); } void runtest2a() { test2<int, int*>(static_cast<int*>(nullptr)); } void runtest2b() { test2<int, int*>(nullptr); }