Bryan Fok
Bryan Fok

Reputation: 3487

What's the different between make_pair and pair?

If you run the below code, you will print 3412, which mean std::make_pair ignored the std::ref here. I want to do understand what is happening here?

using Callback = std::function<void ()>;

struct Test
{
    void operator()()
    {
        std::cout << a ;
    };

    int a;
};


struct Sub
{
void Subscribe(Callback callback)
{
    callback_ = callback;
}

void trigger()
{
     callback_();
}

Callback callback_;
};



int main() {
    std::vector<std::pair<Callback, int>> test_vtor;  
    std::unordered_map<int, Test > test_map;


    test_map[1].a = 1;
    test_map[2].a = 2;
    test_vtor.push_back(std::pair<Callback, int>(std::ref(test_map[1]), 1));
    test_vtor.push_back(std::pair<Callback, int>(std::ref(test_map[2]), 2));

    test_vtor.push_back(std::make_pair(std::ref(test_map[1]), 1));
    test_vtor.push_back(std::make_pair(std::ref(test_map[2]), 2));

    test_map[1].a = 3;
    test_map[2].a = 4;

    std::for_each(test_vtor.begin(), 
                    test_vtor.end(), 
                    [&](auto& pair){
                        pair.first(); 
                });
}

Upvotes: 1

Views: 736

Answers (1)

Dean Seo
Dean Seo

Reputation: 5683

So on from this answer, std::ref does not work with test_vtor as follows:

std::vector<std::pair<Callback, int>> test_vtor; 

Even if you pass a reference:

test_vtor.push_back(std::make_pair(std::ref(test_map[1]), 1));

you cannot avoid your Callback being copied. That's the same reason that declaring std::pair<Callback&, int> is not allowed.

Even if std::make_pair has this exceptional rule for std::reference_wrapper as follows:

... unless application of std::decay results in std::reference_wrapper<X> for some type X, in which case the deduced type is X&.

There will be always a new copy of Callback in test_vtor (whether it's moved or copied), which will surpass its reference-ness during the construction.

Upvotes: 2

Related Questions