Bug 83181 - [C++17] Invalid deduction guide accepted
Summary: [C++17] Invalid deduction guide accepted
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 7.2.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2017-11-27 16:43 UTC by Jonathan Wakely
Modified: 2023-12-29 20:52 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-09-16 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2017-11-27 16:43:08 UTC
template<bool> struct enable_if { using type = void; };
template<> struct enable_if<false> { };
template<typename T> struct is_foo { static const bool value = false; };

template<typename T>
using RequireFoo = typename enable_if<is_foo<T>::value>::type;

template<typename T> struct init_list { };

template<typename T, typename A> struct X
{
  X(init_list<T>, A) { }
};

template<typename T, typename A, /* typename = */ RequireFoo<A>>
  X(init_list<T>, A) -> X<T, A>;

struct Alloc { };

template<> struct is_foo<Alloc> { static const bool value = true; };

int main()
{
  init_list<int> l;
  Alloc a;
  X x(l, a);
}

The RequireFoo<A> template parameter is invalid (it's missing "typename =") but G++ accepts it. CLang rejects it with this error:


prog.cc:15:49: error: deduction guide template contains a template parameter that cannot be deduced
template<typename T, typename A, RequireFoo<A>> X(init_list<T>, A) -> X<T, A>;
                                                ^
prog.cc:15:47: note: non-deducible template parameter (anonymous)
template<typename T, typename A, RequireFoo<A>> X(init_list<T>, A) -> X<T, A>;
                                              ^
Comment 1 TC 2017-12-13 23:41:07 UTC
What's happening here is that a deduction failure occurs with the deduction guide (substitution yields a template non-type parameter of type void whose argument also can't be deduced) and so it is eliminated from the overload set, but there's still an implicit guide generated from the constructor and the deduction is done from that.

[temp.param]/15 proscribes deduction guide templates with a template parameter that neither is deducible nor has a default argument, so this should be diagnosed.
Comment 2 Marek Polacek 2020-09-16 19:57:40 UTC
Still accepted.
Comment 3 Eddie Nolan 2023-12-29 20:52:04 UTC
Here's another example:

template <typename T, typename U>
struct foo {};

template<typename T, typename U>
foo(T&&) -> foo<T, U>;

Clang says:

<source>:5:1: error: deduction guide template contains a template parameter that cannot be deduced
    5 | foo(T&&) -> foo<T, U>;
      | ^
<source>:4:31: note: non-deducible template parameter 'U'
    4 | template<typename T, typename U>
      |                               ^

But GCC accepts it.