1

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; });
      |           
glades
  • 3,778
  • 1
  • 12
  • 34

1 Answers1

1

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.

felix
  • 2,213
  • 7
  • 16
  • you removed the constraint – 463035818_is_not_an_ai Jan 20 '23 at 08:48
  • What do you mean by remove the constraint? I admit that I change the constraint, `entity` is constrained by concept `X`. – felix Jan 20 '23 at 08:50
  • `std::convertible_to> Cb` – 463035818_is_not_an_ai Jan 20 '23 at 08:51
  • In the example, `R` is `int`, and `std::packaged_task` is not defined. If you mean `std::packaged_task`, its constructor is explicit. It is not convertible from a callable in the first place. – felix Jan 20 '23 at 09:00
  • i mean the constraints OP has in their code (yes it has a typo, but anyhow `is_convertible` is the wrong one), the question is how to constrain the constructor argument and have a deduction guide. – 463035818_is_not_an_ai Jan 20 '23 at 09:02
  • I try to follow the original code snippet as close as possible. But I have to modify the code somehow. The last time I check, my workaround constrains the constructor and has a deduction guide. If you don't like the the concept `X` I come up with, I can use `std::constructible_from`. – felix Jan 20 '23 at 09:04
  • sorry I missed the last edit. now your code has a constraint – 463035818_is_not_an_ai Jan 20 '23 at 09:05
  • The first version has a constraint too, but anyway. It's aright. – felix Jan 20 '23 at 09:06
  • your first version had no constraint to require that `fn` can be used to cniostruct the `std::packackaged_task`. – 463035818_is_not_an_ai Jan 20 '23 at 09:07
  • Why did you prefer invoke_result_t instead of decltype? – glades Jan 20 '23 at 09:18
  • OK. I get your point now. I think that I understood your point the moment when I decide to use `std::constructible_from`. But I miss it shortly afterward... Yes, I removed the constraint, my bad. : P – felix Jan 20 '23 at 09:19
  • @glades `invoke_result_t` also works with pointer to member function. It's name is more suggestive than `decltype`. – felix Jan 20 '23 at 09:25
  • @felix Ok, but that would mean I need to arrange the call seperately from the others. That's currently not something I had in mind but I'll think about it. – glades Jan 20 '23 at 09:31
  • Constraint can also be applied to deduction guide BTW [Demo](https://godbolt.org/z/Ebqxv4ozd). – Jarod42 Jan 20 '23 at 14:58