簡體   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