Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

std::binary_search and lower_bound with array of unique_ptr

I’ve been trying to use std::binary_search and std::lower_bound on std::array<unique_ptr<int>> just to get to grips with it. I was having trouble with the following :

#include <array>
#include <memory>
#include <algorithm>

int main() {
    std::array<std::unique_ptr<int>, 3> a = {std::make_unique<int>(1), 
    std::make_unique<int>(2), std::make_unique<int>(5)};

    auto t = std::binary_search(a.begin(), a.end(), 5, [] 
    (std::unique_ptr<int> x, std::unique_ptr<int> y) {
        return x.get() < y.get();
    });
return 0;
}

I’m trying to put my own comparison here, similar to how it would be done with something like std::sort. However when compiling this I have an error cannot convert argument 1 from 'const _Ty' to 'std::unique_ptr<int,std::default_delete<int>>'

What should I change to make this work?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

EDIT : complete error message from Visual Studio

Severity    Code    Description Project File    Line    Suppression State   Details
Error   C2664   'bool thng_already::<lambda_1>::operator ()(std::unique_ptr<int,std::default_delete<int>>,std::unique_ptr<int,std::default_delete<int>>) const': cannot convert argument 1 from 'const _Ty' to 'std::unique_ptr<int,std::default_delete<int>>'
        with
        [
            _Ty=int
        ]   Proj    C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\include\algorithm 7028        

When replacing 5 with std::make_unique<int>(5) we have a different error

Severity    Code    Description Project File    Line    Suppression State   Details
Error   C2280   'std::unique_ptr<int,std::default_delete<int>>::unique_ptr(const std::unique_ptr<int,std::default_delete<int>> &)': attempting to reference a deleted function  Proj    C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\include\algorithm 7028        

>Solution :

There are three issues:

  1. Your lambda takes its parameters by value. This implies that the binary_search implementation has to copy the arguments when passing them to the lambda. Can you copy unique_ptr? No. That’s why it’s not working. Take the arguments by const reference instead.

  2. The lambda cannot accept 5 as one of its arguments since 5 is not a unique_ptr<int>

  3. You Compare x.get() < y.get(). get() returns the raw pointer to the integer, so you compare pointers, not the values that these pointers point to. I assume you mean *x < *y to compare the integers instead

int main() {
    std::array<std::unique_ptr<int>, 3> a = {
            std::make_unique<int>(1), 
            std::make_unique<int>(2),
            std::make_unique<int>(5)};
    auto t = std::binary_search(a.begin(), a.end(),
            std::make_unique<int>(5),
            [](const std::unique_ptr<int>& x, const std::unique_ptr<int>& y) {
        return *x < *y;
    });
    return 0;
}

Feel free to shorten the lambda declaration to [](const auto& x, const auto& y) and rely on type deduction.

Avoiding the temporary allocation

Calling make_unique<int>(5) does a temporary allocation that is not strictly necessary. To avoid it, we need to augment the comparator to accept int and std::unique_ptr<int> as its arguments in either order. This is probably the easiest approach to do so:

    struct Compare {
        bool operator()(const std::unique_ptr<int>& left, int right) const
        { return *left < right; }
        bool operator()(int left, const std::unique_ptr<int>& right) const
        { return left < *right; }
    };
    auto t = std::binary_search(begin, end, val, Compare{});
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading