Home > database >  std::pair with reference to unique pointer
std::pair with reference to unique pointer

Time:08-28

Currently using C 20, GCC 11.1.0

I'm trying to create a class method that returns a std::pair of uint32_t and a reference to a unique pointer. The unique pointer comes from a vector of unique pointers stored as a variable in the class. However, it keeps saying:

error: could not convert ‘std::make_pair(_T1&&, _T2&&) [with _T1 = unsigned int; _T2 = std::unique_ptr<Panel>&; typename std::__strip_reference_wrapper<typename std::decay<_Tp2>::type>::__type = std::unique_ptr<Panel>; typename std::decay<_Tp2>::type = std::decay<std::unique_ptr<Panel>&>::type; typename std::__strip_reference_wrapper<typename std::decay<_Tp>::type>::__type = unsigned int; typename std::decay<_Tp>::type = unsigned int]((* &((Screen*)this)->Screen::panels.std::vector<std::unique_ptr<Panel> >::emplace_back<>()))’ from ‘pair<[...],std::unique_ptr<Panel>>’ to ‘pair<[...],std::unique_ptr<Panel>&>’
   67 |         return std::make_pair<PanelID, Panel_Ptr&>(
      |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
      |                                                   |
      |                                                   pair<[...],std::unique_ptr<Panel>>
   68 |             std::move(panelID), panels.emplace_back());
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Screen
{
private:
    using PanelID = uint32_t;
    using Panel_Ptr = std::unique_ptr<Panel>;
    std::vector<Panel_Ptr> panels {};

public:
    std::pair<PanelID, Panel_Ptr&> foo()
    {
        PanelID panelID {static_cast<PanelID>(panels.size())};
        return std::make_pair<PanelID, Panel_Ptr&>(
            std::move(panelID), panels.emplace_back());
    }
};

CodePudding user response:

std::make_pair() will automatically decay any references given to it to their value types.

The deduced types V1 and V2 are std::decay<T1>::type and std::decay<T2>::type (the usual type transformations applied to arguments of functions passed by value) unless application of std::decay results in std::reference_wrapper<X> for some type X, in which case the deduced type is X&.

https://en.cppreference.com/w/cpp/utility/pair/make_pair

Remove your explicit instantiation of the type parameters of std::make_pair() and wrap the emplace_back() call with std::ref:

return std::make_pair(
    std::move(panelID), 
    std::ref(panels.emplace_back())
);

Alternatively, you can explicitly make the std::pair:

return std::pair<PanelID, Panel_Ptr&>(
    std::move(panelID), 
    panels.emplace_back()
);

Finally, to note on your code, you are calling std::move() on your PanelID type even though it is just an integer. std::move() is useless in that scenario, so removing it entirely would make your code clearer.

Though, putting it on a separate line is still necessary due to the unspecified order of evaluation of arguments passed to functions. Good awareness of this fact.

  •  Tags:  
  • c
  • Related