繁体   English   中英

如何在C ++中声明std :: bind的std :: invoke_result?

[英]How to declare std::invoke_result of std::bind in C++?

我想用自定义删除器声明std::unique_ptr ,它将某些参数绑定到特定的函数:

using namespace std::placeholders;
using HandleDeleter = std::invoke_result_t<std::bind, _1, SOME_FLAG>; // !!!
using HandlePtr = std::unique_ptr<handle_t, HandleDeleter>;

void handle_destroy(handle_t *, int flags);
handle_t * raw_handle;

auto deleter = std::bind(handle_destroy, _1, SOME_FLAG);
HandlePtr ptr(raw_handle, deleter);

这是行不通的,因为std::bind本身是一个巨大的模板构造,具有未指定的返回类型。

如何在我的情况下正确声明HandleDeleter

std::bind不是单个可调用对象,而是一个函数模板。 因此,您必须选择将哪一个传递给std::invoke_result_t ,这确实很麻烦。

幸运的是,还有更好的选择:

  1. 使用decltype

     using deleter_t = decltype(std::bind(handle_destroy, _1, SOME_FLAG)); 
  2. 为该类使用template-argument-deduction:

     unique_ptr ptr(raw_handle, deleter); 

无论如何,由于对使用的函数和参数进行了硬编码,因此不使用std::bind()通常更为简单,并且效率更高。 尽管您当然可以自由地仅使用硬编码部分:

  1. 使用lambda代替std::bind() 在C ++ 20中,无状态lambda甚至会变为默认可构造的:

     auto deleter = [](handle_t* p){ handle_destroy(p, SOME_FLAG); }; 
  2. 定义自己的自定义删除器类,而不是使用std::bind

     struct deleter_t { constexpr void operator()(handle_t* p) const noexcept { handle_destroy(p, SOME_FLAG); } }; 

这是行不通的,因为std::bind本身是一个巨大的模板构造,具有未指定的返回类型。

这提示:您可能使用了错误的工具来完成工作。

我会改用一个简单的struct

struct HandleDeleter
{
    int _flag;
    void operator()(handle_t* h) const
    {
        handle_destroy(h, _flag);
    }
};

HandlePtr ptr(raw_handle, HandleDeleter{SOME_FLAG});

在现代C ++中不建议使用std::bind 请改用lambda(或struct)。 std::bind 在Stephan T. Lavavej的演讲中很好地解释了几个问题:“功能:新增功能和正确使用方法”

对话截图

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM