https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93992

            Bug ID: 93992
           Summary: faile to compile specialization of inner class with
                    template template parameter pack
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: yawaraka.7-11.hemogurobin at ezweb dot ne.jp
  Target Milestone: ---

// Source

#include <iostream>
#include <type_traits>
#include <typeinfo>
#include <array>

template<typename T, T... Value> class A {
};

template<typename T, template<T...> class, T...> struct args_union;
template<typename T, template<T...> class TemplateType, T Head, T... Tail>
struct args_union<T, TemplateType, Head, Tail...> {
        template<T...> struct args_union_sub;
        template<T Head2, T... Tail2> struct args_union_sub<Head2, Tail2...> {
                template<T... Args> using template_type =                       
                        std::conditional_t<(Head2 < Head), TemplateType<Head2,
Args...>,        // if (Head2 < Head) TemplateType<Head2, Args...>;
                        TemplateType<Head, Args...>>;                          
                                                // else TemplateType<Head,
Args...>;

                using type = std::conditional_t<Head == Head2,                 
                                                                               
        // if (Head == Head2)
                        typename args_union<T, template_type,
Tail...>::template args_union_sub<Tail2...>::type,                //   
args_union、args_union_sub
                        std::conditional_t<(Head < Head2),                     
                                                                               
                        // else if (Head < Head2)
                        typename args_union<T, template_type,
Tail...>::template args_union_sub<Head2, Tail2...>::type, //    args_union
                                                                               
                                                                               
                                                        // else
                        typename args_union<T, template_type, Head,
Tail...>::template args_union_sub<Tail2...>::type>>;//    args_union_sub
        };
        template<> struct args_union_sub<> {
                template<T... Args> using template_type = TemplateType<>;
                using type = TemplateType<Head, Tail...>;
        };
};

template<typename T, template<T...> class TemplateType> struct args_union<T,
TemplateType> {
        template<T...> struct args_union_sub;
        template<T Head2, T... Tail2> struct args_union_sub<Head2, Tail2...> {
                template<T... Args> using template_type = TemplateType<Head2,
Tail2..., Args...>;
                using type = TemplateType<Head2, Tail2...>;
        };
        template<> struct args_union_sub<> {
                template<T... Args> using template_type = TemplateType<>;
                using type = TemplateType<>;
        };
};

template<typename T> struct Asub {
        template<T... Value> using type = A<T, Value...>;
};

template<typename T, T... Value1, T... Value2> constexpr auto tmp_union(const
A<T, Value1...>&, const A<T, Value2...>&) {
        return typename args_union<T, Asub<T>::template type,
Value1...>::template args_union_sub<Value2...>::type();
}

int main() {
        A<int, 0, 1, 4, 6> a;
        A<int, 1, 2, 4, 5> b;  
    std::cout << std::boolalpha << std::is_same_v<decltype(tmp_union(a, b)),
A<int, 0, 1, 2, 4, 5, 6>> << std::endl;
        std::cout << typeid(tmp_union(a, b)).name() << std::endl;
}

// error message
Using built-in specs.
COLLECT_GCC=/opt/wandbox/gcc-head/bin/g++
COLLECT_LTO_WRAPPER=/opt/wandbox/gcc-head/libexec/gcc/x86_64-pc-linux-gnu/10.0.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../source/configure --prefix=/opt/wandbox/gcc-head
--enable-languages=c,c++ --disable-multilib --without-ppl --without-cloog-ppl
--enable-checking=release --disable-nls --enable-lto
LDFLAGS=-Wl,-rpath,/opt/wandbox/gcc-head/lib,-rpath,/opt/wandbox/gcc-head/lib64,-rpath,/opt/wandbox/gcc-head/lib32
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.0.1 20200229 (experimental) (GCC) 
COLLECT_GCC_OPTIONS='-o' 'prog.exe' '-I' '/opt/wandbox/boost-sml/include' '-I'
'/opt/wandbox/boost-di/include' '-I' '/opt/wandbox/range-v3/include' '-I'
'/opt/wandbox/nlohmann-json/include' '-I' '/opt/wandbox/cmcstl2/include' '-I'
'/opt/wandbox/te/include' '-Wall' '-Wextra' '-O2' '-march=native' '-v'
'-std=gnu++2a' '-I' '/opt/wandbox/boost-1.72.0/gcc-head/include'
'-L/opt/wandbox/boost-1.72.0/gcc-head/lib' '-shared-libgcc'
 /opt/wandbox/gcc-head/libexec/gcc/x86_64-pc-linux-gnu/10.0.1/cc1plus -quiet -v
-I /opt/wandbox/boost-sml/include -I /opt/wandbox/boost-di/include -I
/opt/wandbox/range-v3/include -I /opt/wandbox/nlohmann-json/include -I
/opt/wandbox/cmcstl2/include -I /opt/wandbox/te/include -I
/opt/wandbox/boost-1.72.0/gcc-head/include -imultiarch x86_64-linux-gnu
-D_GNU_SOURCE prog.cc -march=sandybridge -mmmx -mno-3dnow -msse -msse2 -msse3
-mssse3 -mno-sse4a -mcx16 -msahf -mno-movbe -maes -mno-sha -mpclmul -mpopcnt
-mno-abm -mno-lwp -mno-fma -mno-fma4 -mno-xop -mno-bmi -mno-sgx -mno-bmi2
-mno-pconfig -mno-wbnoinvd -mno-tbm -mavx -mno-avx2 -msse4.2 -msse4.1
-mno-lzcnt -mno-rtm -mno-hle -mno-rdrnd -mno-f16c -mno-fsgsbase -mno-rdseed
-mno-prfchw -mno-adx -mfxsr -mxsave -mxsaveopt -mno-avx512f -mno-avx512er
-mno-avx512cd -mno-avx512pf -mno-prefetchwt1 -mno-clflushopt -mno-xsavec
-mno-xsaves -mno-avx512dq -mno-avx512bw -mno-avx512vl -mno-avx512ifma
-mno-avx512vbmi -mno-avx5124fmaps -mno-avx5124vnniw -mno-clwb -mno-mwaitx
-mno-clzero -mno-pku -mno-rdpid -mno-gfni -mno-shstk -mno-avx512vbmi2
-mno-avx512vnni -mno-vaes -mno-vpclmulqdq -mno-avx512bitalg -mno-movdiri
-mno-movdir64b -mno-waitpkg -mno-cldemote -mno-ptwrite -mno-avx512bf16
-mno-enqcmd -mno-avx512vp2intersect --param l1-cache-size=32 --param
l1-cache-line-size=64 --param l2-cache-size=4096 -mtune=sandybridge -quiet
-dumpbase prog.cc -auxbase prog -O2 -Wall -Wextra -std=gnu++2a -version -o
/tmp/cczxYwwS.s
GNU C++17 (GCC) version 10.0.1 20200229 (experimental) (x86_64-pc-linux-gnu)
        compiled by GNU C version 10.0.1 20200229 (experimental), GMP version
6.1.0, MPFR version 3.1.4, MPC version 1.0.3, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/local/include"
ignoring nonexistent directory
"/opt/wandbox/gcc-head/lib/gcc/x86_64-pc-linux-gnu/10.0.1/../../../../x86_64-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /opt/wandbox/boost-sml/include
 /opt/wandbox/boost-di/include
 /opt/wandbox/range-v3/include
 /opt/wandbox/nlohmann-json/include
 /opt/wandbox/cmcstl2/include
 /opt/wandbox/te/include
 /opt/wandbox/boost-1.72.0/gcc-head/include

/opt/wandbox/gcc-head/lib/gcc/x86_64-pc-linux-gnu/10.0.1/../../../../include/c++/10.0.1

/opt/wandbox/gcc-head/lib/gcc/x86_64-pc-linux-gnu/10.0.1/../../../../include/c++/10.0.1/x86_64-pc-linux-gnu

/opt/wandbox/gcc-head/lib/gcc/x86_64-pc-linux-gnu/10.0.1/../../../../include/c++/10.0.1/backward
 /opt/wandbox/gcc-head/lib/gcc/x86_64-pc-linux-gnu/10.0.1/include
 /opt/wandbox/gcc-head/include
 /opt/wandbox/gcc-head/lib/gcc/x86_64-pc-linux-gnu/10.0.1/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
GNU C++17 (GCC) version 10.0.1 20200229 (experimental) (x86_64-pc-linux-gnu)
        compiled by GNU C version 10.0.1 20200229 (experimental), GMP version
6.1.0, MPFR version 3.1.4, MPC version 1.0.3, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 1af50902123577608ff32d1ca7d8f798
prog.cc:24:11: error: explicit specialization in non-namespace scope 'struct
args_union<T, TemplateType, Head, Tail ...>'
   24 |  template<> struct args_union_sub<> {
      |           ^
prog.cc:24:20: error: template parameters not deducible in partial
specialization:
   24 |  template<> struct args_union_sub<> {
      |                    ^~~~~~~~~~~~~~~~
prog.cc:24:20: note:         'T'
prog.cc:24:20: note:         'template<T ...<anonymous> > class TemplateType'
prog.cc:24:20: note:         'Head'
prog.cc:24:20: note:         'Tail'
prog.cc:36:11: error: explicit specialization in non-namespace scope 'struct
args_union<T, TemplateType>'
   36 |  template<> struct args_union_sub<> {
      |           ^
prog.cc:36:20: error: template parameters not deducible in partial
specialization:
   36 |  template<> struct args_union_sub<> {
      |                    ^~~~~~~~~~~~~~~~
prog.cc:36:20: note:         'T'
prog.cc:36:20: note:         'template<T ...<anonymous> > class TemplateType'
prog.cc: In instantiation of 'struct args_union<int, args_union<int,
args_union<int, args_union<int, Asub<int>::type, 0, 1, 4, 6>::args_union_sub<1,
2, 4, 5>::template_type, 1, 4, 6>::args_union_sub<2, 4, 5>::template_type, 4,
6>::args_union_sub<4, 5>::template_type, 6>::args_union_sub<5>':
prog.cc:17:9:   recursively required from 'struct args_union<int,
args_union<int, Asub<int>::type, 0, 1, 4, 6>::args_union_sub<1, 2, 4,
5>::template_type, 1, 4, 6>::args_union_sub<2, 4, 5>'
prog.cc:17:9:   required from 'struct args_union<int, Asub<int>::type, 0, 1, 4,
6>::args_union_sub<1, 2, 4, 5>'
prog.cc:47:104:   required from 'constexpr auto tmp_union(const A<T, Value1
...>&, const A<T, Value2 ...>&) [with T = int; T ...Value1 = {0, 1, 4, 6}; T
...Value2 = {1, 2, 4, 5}]'
prog.cc:53:74:   required from here
prog.cc:17:9: error: invalid use of incomplete type 'struct args_union<int,
args_union<int, args_union<int, args_union<int, args_union<int,
Asub<int>::type, 0, 1, 4, 6>::args_union_sub<1, 2, 4, 5>::template_type, 1, 4,
6>::args_union_sub<2, 4, 5>::template_type, 4, 6>::args_union_sub<4,
5>::template_type, 6>::args_union_sub<5>::template_type>::args_union_sub<>'
   17 |   using type = std::conditional_t<Head == Head2,              // if
(Head == Head2)
      |         ^~~~
prog.cc:31:24: note: declaration of 'struct args_union<int, args_union<int,
args_union<int, args_union<int, args_union<int, Asub<int>::type, 0, 1, 4,
6>::args_union_sub<1, 2, 4, 5>::template_type, 1, 4, 6>::args_union_sub<2, 4,
5>::template_type, 4, 6>::args_union_sub<4, 5>::template_type,
6>::args_union_sub<5>::template_type>::args_union_sub<>'
   31 |  template<T...> struct args_union_sub;
      |                        ^~~~~~~~~~~~~~
prog.cc: In function 'int main()':
prog.cc:53:41: error: template argument 1 is invalid
   53 |     std::cout << std::boolalpha << std::is_same_v<decltype(tmp_union(a,
b)), A<int, 0, 1, 2, 4, 5, 6>> << std::endl;
      |                                        
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// command line

$ g++ prog.cc -Wall -Wextra -O2 -march=native -v
-I/opt/wandbox/boost-1.72.0/gcc-head/include -std=gnu++2a

// comment

compiled on Wandbox. URL: https://wandbox.org/permlink/7hblGLSOhTyVBK4V
Clang 11.0.0 and MSVC 16.4.5 compile this code successfully.

Reply via email to