代码之家  ›  专栏  ›  技术社区  ›  bers

如何在std::apply中封装std::make_unique?

  •  1
  • bers  · 技术社区  · 1 年前

    以下内容未编译:

    #include <memory>
    #include <tuple>
    #include <utility>
    
    int main()
    {
        std::apply(std::make_unique<int>, std::make_tuple(1));
        
        return 0;
    }
    

    错误消息:

    In file included from /usr/include/c++/11/bits/unique_ptr.h:37,
                     from /usr/include/c++/11/memory:76,
                     from main.cpp:1:
    /usr/include/c++/11/tuple: In instantiation of ‘constexpr decltype(auto) std::__apply_impl(_Fn&&, _Tuple&&, std::index_sequence<_Idx ...>) [with _Fn = std::unique_ptr<int, std::default_delete<int> > (&)(); _Tuple = std::tuple<int>; long unsigned int ..._Idx = {0}; std::index_sequence<_Idx ...> = std::integer_sequence<long unsigned int, 0>]’:
    /usr/include/c++/11/tuple:1869:31:   required from ‘constexpr decltype(auto) std::apply(_Fn&&, _Tuple&&) [with _Fn = std::unique_ptr<int, std::default_delete<int> > (&)(); _Tuple = std::tuple<int>]’
    main.cpp:7:15:   required from here
    /usr/include/c++/11/tuple:1858:27: error: no matching function for call to ‘__invoke(std::unique_ptr > (&)(), std::__tuple_element_t<0, std::tuple >)’
     1858 |       return std::__invoke(std::forward<_Fn>(__f),
          |              ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
     1859 |                            std::get<_Idx>(std::forward<_Tuple>(__t))...);
          |                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from /usr/include/c++/11/tuple:41,
                     from /usr/include/c++/11/bits/unique_ptr.h:37,
                     from /usr/include/c++/11/memory:76,
                     from main.cpp:1:
    /usr/include/c++/11/bits/invoke.h:90:5: note: candidate: ‘template constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...)’
       90 |     __invoke(_Callable&& __fn, _Args&&... __args)
          |     ^~~~~~~~
    /usr/include/c++/11/bits/invoke.h:90:5: note:   template argument deduction/substitution failed:
    /usr/include/c++/11/bits/invoke.h: In substitution of ‘template<class _Callable, class ... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = std::unique_ptr<int, std::default_delete<int> > (&)(); _Args = {int}]’:
    /usr/include/c++/11/tuple:1858:27:   required from ‘constexpr decltype(auto) std::__apply_impl(_Fn&&, _Tuple&&, std::index_sequence<_Idx ...>) [with _Fn = std::unique_ptr<int, std::default_delete<int> > (&)(); _Tuple = std::tuple<int>; long unsigned int ..._Idx = {0}; std::index_sequence<_Idx ...> = std::integer_sequence<long unsigned int, 0>]’
    /usr/include/c++/11/tuple:1869:31:   required from ‘constexpr decltype(auto) std::apply(_Fn&&, _Tuple&&) [with _Fn = std::unique_ptr<int, std::default_delete<int> > (&)(); _Tuple = std::tuple<int>]’
    main.cpp:7:15:   required from here
    /usr/include/c++/11/bits/invoke.h:90:5: error: no type named ‘type’ in ‘struct std::__invoke_result > (&)(), int>’
    

    这怎么能解决?

    1 回复  |  直到 1 年前
        1
  •  3
  •   NathanOliver    1 年前

    C++17及更早版本

    std::make_unique<int> 具有类型 std::unique_ptr<int>() 这是一个返回 std::unique_ptr<int> 并且不采用任何参数。这不是您想要的,因为您正在向函数传递值。

    你需要的是 std::make_unique<int, int> 具有类型 std::unique_ptr<int>(int) 这就是你想要的。第一个模板参数用于的类型 unique_ptr 并且每个附加类型用于make函数的参数类型。

    C++20+

    自C++20以来 make_unique 不是可寻址函数,因此不再允许在可移植代码中使用此技术。相反,您需要利用lambda来实现间接级别,如

    std::apply([](auto&& var){ return std::make_unique<int>(decltype(var)(var)); }, std::make_tuple(1));