Constrain an input type in deduction guide

113 views Asked by At

I want my class object's ctor to accept a functor that is able to be converted to a std::packaged_task<R()> whereas R is auto deduced from the functor's return value. Here's what I've got so far:

Demo

#include <utility>
#include <future>
#include <concepts>
#include <cstdio>


template <typename R>
struct entity
{
    
    template <std::convertible_to<std::packaged_task<R>> Cb>
    entity(Cb&& fn)
        :   fn_{ std::move(fn) }
    { }

    std::packaged_task<R()> fn_;
};


template <typename U, std::convertible_to<std::packaged_task<U()>> Cb>
entity(Cb&& fn) -> entity<decltype(fn())>;

int main()
{
    entity e([]{ return 10; });
}

Even though I'm providing a deduction guide, my naive approach doesn't work. I suspect it has to do with the deduction guide specifying std::convertible_to<std::packaged_task<U()>> concept where gcc is struggling to substitute U for any type, hence making the deduction guide worthless. Can this be augmented?

<source>:12:5: note:   template argument deduction/substitution failed:
<source>:25:30: note:   couldn't deduce template parameter 'R'
   25 |     entity e([]{ return 10; });
      |           
1

There are 1 answers

14
felix On

I managed to find a workaround. The idea is to first get the return type of the Callable, then check the return type by constraining the constructor.

template <typename R>
struct entity {
  template <class Cb> requires std::constructible_from<std::packaged_task<R()>, Cb &&>
  entity(Cb &&fn) : fn_(std::forward<Cb>(fn)) {}

  std::packaged_task<R()> fn_;
};

template <class Cb>
entity(Cb &&) -> entity<std::invoke_result_t<Cb &&>>;

int main()
{
  entity e([]{ return 10; });
}

The issue in your code snippet is (I believe):

template <typename U, std::convertible_to<std::packaged_task<U()>> Cb>
entity(Cb&& fn) -> entity<decltype(fn())>;

U is not used in the parameter list of entity, thus it is not deduced during the template argument deduction. It tries to deduce Cb, but Cb depends on U.

The generated deduction guide from entity constructor has the same issue. R cannot be deduced.