public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/114695] New: Template argument deduction and defaulted template template parameters
@ 2024-04-11 16:45 vin.piquet at gmail dot com
  2024-04-11 23:44 ` [Bug c++/114695] " pinskia at gcc dot gnu.org
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: vin.piquet at gmail dot com @ 2024-04-11 16:45 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 114695
           Summary: Template argument deduction and defaulted template
                    template parameters
           Product: gcc
           Version: 13.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vin.piquet at gmail dot com
  Target Milestone: ---

==== test.cpp ====
template <int Y, typename X> struct Bar {
    void accept(X value) { }
};

template <typename...> struct Foo;

template <int... Is, typename... Ts>
struct Foo<Bar<Is, Ts>...> : Bar<Is, Ts>... {
    template <typename T, int I, template <int, typename> typename B = Bar>
    constexpr static B<I, T>* slice_by_type(B<I, T>* self) {
        return self;
    }

    template <typename... Us>
    void accept(Us... values) {
        (slice_by_type<Us>(this)->accept(values), ...);
    }
};

int main() {
    Foo<Bar<0, float>, Bar<1, int>> foo;
    foo.accept(3.14f, 10);
}
==== test.cpp ====

GCC rejects this code with the following error

==== console output for GCC 13.2 ====
test.cpp: In instantiation of 'void Foo<Bar<Is, Ts>...>::accept(Us ...) [with
Us = {float, int}; int ...Is = {0, 1}; Ts = {float, int}]':
test.cpp:22:15:   required from here
test.cpp:16:27: error: no matching function for call to 'Foo<Bar<0, float>,
Bar<1, int> >::slice_by_type<float>(Foo<Bar<0, float>, Bar<1, int> >*)'
   16 |         (slice_by_type<Us>(this)->accept(values), ...);
      |          ~~~~~~~~~~~~~~~~~^~~~~~
test.cpp:10:31: note: candidate: 'template<class T, int I, template<int
<anonymous>, class> class B> static constexpr B<I, T>* Foo<Bar<Is,
Ts>...>::slice_by_type(B<I, T>*) [with int I = T; B = I; int ...Is = {0, 1}; Ts
= {float, int}]'
   10 |     constexpr static B<I, T>* slice_by_type(B<I, T>* self) {
      |                               ^~~~~~~~~~~~~
test.cpp:10:31: note:   template argument deduction/substitution failed:
test.cpp:16:27: note:   'B<I, T>' is an ambiguous base class of 'Foo<Bar<0,
float>, Bar<1, int> >'
   16 |         (slice_by_type<Us>(this)->accept(values), ...);
      |          ~~~~~~~~~~~~~~~~~^~~~~~

This appears to be a consequence of GCC matching T to I somehow and getting
confused. I can't really tell what's going on here, except that the fact GCC
seems to not deduce I = 0 supposedly because B<I, T> is not deduced to Bar<0,
float>.

Interestingly, GCC 6.3 also rejects this code, with a somewhat more clear
error:

==== Console output for GCC 6.3 ====
test.cpp: In instantiation of 'void Foo<Bar<Is, Ts>...>::accept(Us ...) [with
Us = {float, int}; int ...Is = {0, 1}; Ts = {float, int}]':
<source>:22:25:   required from here
<source>:16:27: error: no matching function for call to 'Foo<Bar<0, float>,
Bar<1, int> >::slice_by_type(Foo<Bar<0, float>, Bar<1, int> >*)'
         (slice_by_type<Us>(this)->accept(values), ...);
          ~~~~~~~~~~~~~~~~~^~~~~~
test.cpp:10:31: note: candidate: template<class T, int I, template<int
<anonymous>, class> class B> static constexpr B<I, T>* Foo<Bar<Is,
Ts>...>::slice_by_type(B<I, T>*) [with T = T; int I = I; B = B; int ...Is = {0,
1}; Ts = {float, int}]
     constexpr static B<I, T>* slice_by_type(B<I, T>* self) {
                               ^~~~~~~~~~~~~
test.cpp:10:31: note:   template argument deduction/substitution failed:
test.cpp:16:27: error: type/value mismatch at argument 1 in template parameter
list for 'template<int <anonymous>, class> class B'
         (slice_by_type<Us>(this)->accept(values), ...);
          ~~~~~~~~~~~~~~~~~^~~~~~
test.cpp:16:27: note:   expected a constant of type 'int', got 'Bar<0, float>'
==== Console output for GCC 6.3 ====

MSVC accepts this code in C++20 but rejects it in C++17 with a similar error;
Clang accepts this code on both versions since Clang 5.0.0

Relevant godbolt link: https:~~godbolt.org~z~48zs7KnTo (replace tildes)

==== Compiler version ====
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/aarch64-linux-gnu/13/lto-wrapper
Target: aarch64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 13.2.0-4ubuntu3'
--with-bugurl=file:///usr/share/doc/gcc-13/README.Bugs
--enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr
--with-gcc-major-version-only --program-suffix=-13
--program-prefix=aarch64-linux-gnu- --enable-shared --enable-linker-build-id
--libexecdir=/usr/libexec --without-included-gettext --enable-threads=posix
--libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu
--enable-libstdcxx-debug --enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=new --enable-gnu-unique-object
--disable-libquadmath --disable-libquadmath-support --enable-plugin
--enable-default-pie --with-system-zlib --enable-libphobos-checking=release
--with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch
--enable-fix-cortex-a53-843419 --disable-werror --enable-checking=release
--build=aarch64-linux-gnu --host=aarch64-linux-gnu --target=aarch64-linux-gnu
--with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.2.0 (Ubuntu 13.2.0-4ubuntu3)
==== Compiler version ===

Thank you :)

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug c++/114695] Template argument deduction and defaulted template template parameters
  2024-04-11 16:45 [Bug c++/114695] New: Template argument deduction and defaulted template template parameters vin.piquet at gmail dot com
@ 2024-04-11 23:44 ` pinskia at gcc dot gnu.org
  2024-04-11 23:47 ` pinskia at gcc dot gnu.org
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-04-11 23:44 UTC (permalink / raw)
  To: gcc-bugs

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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2024-04-11
             Status|UNCONFIRMED                 |NEW
     Ever confirmed|0                           |1

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Confirmed; EDG accepts it also in C++17 (and C++20) modes. 

Also note If I change slice_by_type to take Bar instead of the template
argument, it works which makes it feel like for some reason GCC is not able to
deduce the arguments properly.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug c++/114695] Template argument deduction and defaulted template template parameters
  2024-04-11 16:45 [Bug c++/114695] New: Template argument deduction and defaulted template template parameters vin.piquet at gmail dot com
  2024-04-11 23:44 ` [Bug c++/114695] " pinskia at gcc dot gnu.org
@ 2024-04-11 23:47 ` pinskia at gcc dot gnu.org
  2024-04-12  9:24 ` vin.piquet at gmail dot com
  2024-04-12  9:30 ` vin.piquet at gmail dot com
  3 siblings, 0 replies; 5+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-04-11 23:47 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Note you don't need the extra template int argument either to reproduce the
failure:
```

template <typename X> struct Bar {
    void accept(X value) { }
};

template <typename...> struct Foo;

template <typename... Ts>
struct Foo<Bar<Ts>...> : Bar<Ts>... {
    template <typename T, template <typename> class B = ::Bar>
    constexpr static Bar<T>* slice_by_type(B<T>* self) {
        return self;
    }

    template <typename... Us>
    void accept(Us... values) {
        (slice_by_type<Us>(this)->accept(values), ...);
    }
};

int main() {
    Foo<Bar<float>, Bar<int>> foo;
    foo.accept(3.14f, 10);
}
```

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug c++/114695] Template argument deduction and defaulted template template parameters
  2024-04-11 16:45 [Bug c++/114695] New: Template argument deduction and defaulted template template parameters vin.piquet at gmail dot com
  2024-04-11 23:44 ` [Bug c++/114695] " pinskia at gcc dot gnu.org
  2024-04-11 23:47 ` pinskia at gcc dot gnu.org
@ 2024-04-12  9:24 ` vin.piquet at gmail dot com
  2024-04-12  9:30 ` vin.piquet at gmail dot com
  3 siblings, 0 replies; 5+ messages in thread
From: vin.piquet at gmail dot com @ 2024-04-12  9:24 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from Vincent Piquet <vin.piquet at gmail dot com> ---
Interesting. Now I think the issue may actually be caused by pack expansion on
the call site. The issue also happens when Foo only has one base class, albeit
with a different error that at least has concise types on both sides.

==== test.cpp ====
template <typename X> struct Bar {
    void accept(X value) { }
};

template <typename...> struct Foo;

template <typename... Ts>
struct Foo<Bar<Ts>...> : Bar<Ts>... {
    template <typename T, template <typename> typename B = Bar>
    constexpr static B<T>* slice_by_type(B<T>* self) {
        return self;
    }

    template <typename... Us>
    void accept(Us... values) {
        (slice_by_type<Us>(this)->accept(values), ...);
    }
};

int main() {
    Foo<Bar<float>> foo;
    foo.accept(3.14f);
}
==== test.cpp ====

==== GCC 13.2 ====
test.cpp: In instantiation of 'void Foo<Bar<Ts>...>::accept(Us ...) [with Us =
{float}; Ts = {float}]':
test.cpp:22:15:   required from here
test.cpp:16:27: error: no matching function for call to 'Foo<Bar<float>
>::slice_by_type<float>(Foo<Bar<float> >*)'
   16 |         (slice_by_type<Us>(this)->accept(values), ...);
      |          ~~~~~~~~~~~~~~~~~^~~~~~
test.cpp:10:28: note: candidate: 'template<class T, template<class> class B>
static constexpr B<T>* Foo<Bar<Ts>...>::slice_by_type(B<T>*) [with B = T; Ts =
{float}]'
   10 |     constexpr static B<T>* slice_by_type(B<T>* self) {
      |                            ^~~~~~~~~~~~~
test.cpp:10:28: note:   template argument deduction/substitution failed:
test.cpp:16:27: note:   deduced conflicting types for parameter 'T' ('float'
and 'Bar<float>')
   16 |         (slice_by_type<Us>(this)->accept(values), ...);
      |          ~~~~~~~~~~~~~~~~~^~~~~~
==== GCC 13.2 ====

This may however be simplified so much that it becomes another bug. I'm unsure.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug c++/114695] Template argument deduction and defaulted template template parameters
  2024-04-11 16:45 [Bug c++/114695] New: Template argument deduction and defaulted template template parameters vin.piquet at gmail dot com
                   ` (2 preceding siblings ...)
  2024-04-12  9:24 ` vin.piquet at gmail dot com
@ 2024-04-12  9:30 ` vin.piquet at gmail dot com
  3 siblings, 0 replies; 5+ messages in thread
From: vin.piquet at gmail dot com @ 2024-04-12  9:30 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Vincent Piquet <vin.piquet at gmail dot com> ---
Note that MSVC latest now also fails this last sample regardless of the
language version (but the error differs from C++17 to C++20). Clang (>= 5.0.0)
still happily accepts it, on both versions.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-04-12  9:30 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-11 16:45 [Bug c++/114695] New: Template argument deduction and defaulted template template parameters vin.piquet at gmail dot com
2024-04-11 23:44 ` [Bug c++/114695] " pinskia at gcc dot gnu.org
2024-04-11 23:47 ` pinskia at gcc dot gnu.org
2024-04-12  9:24 ` vin.piquet at gmail dot com
2024-04-12  9:30 ` vin.piquet at gmail dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).