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

--- Comment #18 from Frank Heckenbach <f.heckenb...@fh-soft.de> ---
(In reply to Frank Heckenbach from comment #17)
> Maybe I've found a work-around. I took the is_instance_of_v template from
> https://indii.org/blog/is-type-instantiation-of-template/ and turned it into
> a concept, so I can replace:
> 
>   void f (S <auto>);
>   void g (T <auto, auto>);
> 
> with:
>   
>   void f (instance_of <S> auto);
>   void g (instance_of <T> auto);
> 
> which at least keeps the required changes localized.
> 
> I think it won't work with "partially auto instantiations" such as:
>   
>   void g (T <auto, int>);
> 
> But fortunately I don't have many of them.
> 
> Since I'm not so well versed with concepts yet, can you please confirm
> whether this is effectively equivalent?

To answer my own question, no it's not. T <auto> also accepts derived types,
instance_of does not.

So another attempt:

#include <type_traits>

template <            template <typename ...> typename Template, typename ...
U> void CheckIsDerivedFromTemplate (const volatile Template <U ...> &);
template <typename T, template <typename ...> typename Template> concept
DerivedFromTemplate = requires (T v) { CheckIsDerivedFromTemplate <Template>
(v); };

template <typename T> struct S { };
struct U: S <int> { };
struct V: U { };
class W: U { };

void f (S <auto>) { }
void f_ (DerivedFromTemplate <S> auto) { }

int main ()
{
  S <double> a;

  // OK
  f  (a);
  f_ (a);
  f  (S <int> ());
  f_ (S <int> ());
  f  (V ());
  f_ (V ());

  // error
  // f  (1);
  // f_ (1);
  // f  (nullptr);
  // f_ (nullptr);
  // f  (W ());
  // f_ (W ());
}

The diagnostics are worse, especially with W, but at least it accepts V and
rejects W as it should.

So, could this be a viable workaround?

Reply via email to