在扣除指南中约束输入类型

Constrain an input type in deduction guide

提问人:glades 提问时间:1/20/2023 最后编辑:glades 更新时间:1/20/2023 访问量:79

问:

我希望我的类对象的 ctor 接受能够转换为 而 R 是从函子的返回值自动推导出来的函子。这是我目前所得到的:std::packaged_task<R()>

演示

#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; });
}

尽管我提供了推演指南,但我幼稚的方法行不通。我怀疑这与演绎指南指定概念有关,其中 gcc 正在努力用 U 代替任何类型,从而使演绎指南毫无价值。这可以增强吗?std::convertible_to<std::packaged_task<U()>>

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

评论

0赞 463035818_is_not_an_ai 1/20/2023
我想使构造函数参数 a 不是您想要的,因为那样就行不通了。std::packaged_task<U()>entity e([]{ return 10; });
0赞 glades 1/20/2023
@463035818_is_not_a_number 事实上,我必须在 API 中显式地将 lambda 转换为打包任务,这并不理想。
1赞 StoryTeller - Unslander Monica 1/20/2023
只需让扣除指南接受 CB,不受约束,然后提取返回类型即可。c'tor 已经具有防止不需要的回调的约束。
2赞 463035818_is_not_an_ai 1/20/2023
如果我理解正确,则需要隐式转换,但没有隐式转换(记住之前的问题),这就是为什么这个 godbolt.org/z/x58PY8nGM 也失败了(但不是演绎指南)std::is_convertible_to
0赞 glades 1/20/2023
@463035818_is_not_a_number 你们俩都是对的,现在这按预期工作:godbolt.org/z/YnzjjPhh9]

答:

1赞 felix 1/20/2023 #1

我设法找到了解决方法。这个想法是首先获取 Callable 的返回类型,然后通过约束构造函数来检查返回类型。

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; });
}

您的代码片段中的问题是(我相信):

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

U在参数列表中没有使用,因此在模板参数推导过程中不会进行推导。它试图推导出 ,但依赖于 。entityCbCbU

从构造函数生成的推导指南也有同样的问题。 无法推断。entityR

评论

0赞 463035818_is_not_an_ai 1/20/2023
您删除了约束
0赞 felix 1/20/2023
删除约束是什么意思?我承认我改变了约束,受到概念的约束。entityX
0赞 463035818_is_not_an_ai 1/20/2023
std::convertible_to<std::packaged_task<R>> Cb
0赞 felix 1/20/2023
在此示例中,是 ,并且未定义。如果你的意思是,它的构造函数是显式的。它首先不能从可调用转换。Rintstd::packaged_task<R>std::packaged_task<R()>
0赞 463035818_is_not_an_ai 1/20/2023
我的意思是 OP 在其代码中的约束(是的,它有一个错别字,但无论如何都是错误的),问题是如何约束构造函数参数并有一个演绎指南。is_convertible