make_pair() in C++

回眸只為那壹抹淺笑 提交于 2020-01-22 03:48:29

问题


I was doing the problem 337 from leetcode. This is the code I implemented.

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int rob(TreeNode* root) {

        unordered_map<TreeNode*, int> memo;

        return robSub(root, memo);
    }

private:
    int robSub(TreeNode* root, unordered_map<TreeNode*, int>& memo) {

        if (root == nullptr) {
            return 0;
        }

        if (memo.find(root) != memo.end()) {
            return memo.find(root)->second;
        }

        int leftGrand = 0;
        int rightGrand = 0;

        if (root->left != nullptr) {
            leftGrand = robSub(root->left->left, memo) + robSub(root->left->right, memo);
        }
        if (root->right != nullptr) {
            rightGrand = robSub(root->right->left, memo) + robSub(root->right->right, memo);
        }

        int result = max(root->val + leftGrand + rightGrand, robSub(root->left, memo) + robSub(root->right, memo));

        memo.insert(make_pair<TreeNode*, int>(root, result));
        return result;

    }
};

Then it reported an error:

Line 42: Char 59: error: no matching function for call to `make_pair<TreeNode*, int>(TreeNode*&, int&))`

Why the error happened and the arguments in make_pair<>() become references? Can someone help?

I modified make_pair<TreeNode*, int>(root, result) to make_pair(root, result), then it worked. What's the differences between them?


回答1:


TL;DR: Don't specify template arguments of std::make_pair. Let the compiler deduce them.


The meaning of template parameters of std::make_pair was changed in C++11.

It used to be:

template <class T1, class T2> /*...*/ make_pair( T1 t, T2 u );

But now it is:

template <class T1, class T2> /*...*/ make_pair(T1 &&t, T2 &&u);
// `t` and `u` are forwarding references.

The code was valid pre-C++11, but it no longer is.

You could change the template arguments accordingly: make_pair<TreeNode*&, int&>(root, result), but there is no reason to specify them manually. The compiler can deduce them just fine.

If you don't understand why the template arguments have to be references, read about forwarding references.


Why ... the arguments in make_pair<>() become references?

Probably your compiler displayed argument types as references to indicate that you're passing lvalues into make_pair.




回答2:


When you have a

unordered_map<TreeNode*, int>& memo

and you want to insert an element:

memo.insert(make_pair<TreeNode*, int>(root, result));

There are several overloads that would match. My guess (but please think about this a bit) is that you want the one taking a const value_type& as argument. In that case, just construct the pair doing exactly that:

memo.insert(unordered_map<TreeNode*, int>::value_type(root, result));

The sole reason why you use make_pair() is to let the compiler pick the template parameters (less typing, a generic pair<type1, type2> ctor). If you want to specify the types explicitly, you can use the plain pair ctor. In this case though, I'd consider it an implementation detail of unordered_map and instead use its nested typedef. That typedef is btw. std::pair<const Key, T>!

All this leaves me with one question only: Why not use memo[root] = result?



来源:https://stackoverflow.com/questions/59520863/make-pair-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!