簡體   English   中英

'const' 關鍵字改變語義

[英]'const' keyword changing semantics

我在 C++ 中嘗試了今天的 leetcode 挑戰 您必須在二叉樹中找到表親。 這是我的代碼。

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

class Solution {
public:
    bool isCousins(TreeNode* root, int x, int y) {
        this->x = x;
        this->y = y;
        return visit(overloaded{
            [](const bool& r) { 
                return r; 
            },
            [](const optional<int>& r) { 
                return false; 
            }
        }, helper(root));
    }

private:
    int x;
    int y;

    variant<const bool, optional<int>> helper(TreeNode* node) {
        if (node == nullptr) {
            return variant<const bool, optional<int>>((optional<int>()));
        }
        else if (node->val == x) {
            return variant<const bool, optional<int>>(optional<int>(0));
        }
        else if (node->val == y) {
            return variant<const bool, optional<int>>(optional<int>(0));
        }
        else {
            auto l = helper(node -> left);
            auto r = helper(node -> right);
            return visit(overloaded{
                [](const bool& l, optional<int>& r) {
                    assert(!r.has_value());
                    return variant<const bool, optional<int>>(l); 
                },
                [](optional<int>& l, const bool& r) {
                    assert(!l.has_value());
                    return variant<const bool, optional<int>>(r); 
                },
                [](optional<int> l, optional<int> r) {
                    if (l.has_value() && r.has_value()) {
                        return variant<const bool, optional<int>>(*l > 0 && *l == *r);
                    }
                    else if (l.has_value()) { 
                        ++*l;
                        return variant<const bool, optional<int>>(l); 
                    }
                    else if (r.has_value()) { 
                        ++*r;
                        return variant<const bool, optional<int>>(r); 
                    }
                    else {
                        return variant<const bool, optional<int>>((optional<int>())); 
                    }
                }
            }, l, r);
        }
    }
};

一個證明我的問題的測試用例是

[1,3,2,null,null,7,4,null,null,5,6,null,8,null,9]
8
9

上面的代碼運行並成功完成。 但是,如果我在第 10 行( [](bool& r) { )中刪除了一個const關鍵字,那么它會返回一個不同的(不正確的)答案。 const是為了編譯時安全,所以不應該影響語義,但我猜const重載會發生一些奇怪的事情? 究竟是怎么回事?

Possibly related: it also breaks my mental model that if, instead of declaring l , r in lines 34,35, I pass them directly as arguments to visit (ie. return visit(overloaded{..}, helper(node->left), helper(node->right) ), 它也失敗了。我再次希望這對語義沒有影響。

在這種情況下刪除const會更改代碼的含義,通過更改在重載決議中選擇的 function。

考慮以下重載集和調用:

void f(int const &) { std::cout << "i"; }
void f(bool) { std::cout << "b"; }

int main()
{
    int const i = 42;
    f(i); // prints i
    f(42); // prints i
}

兩者都調用第一個 function (如預期的那樣),因為int const &綁定到int const以及int&& (臨時int )。

但是,如果我們刪除重載集的第一個 function 中的const ,並進行相同的調用:

void f(int &) { std::cout << "i"; }
void f(bool) { std::cout << "b"; }

int main()
{
    int const i = 42;
    f(i); // prints b
    f(42); // prints b
}

第一個 function 沒有被選中,因為int &不能綁定到int const 但是, bool可以綁定到int const (在隱式轉換之后),並且它調用第二個 function。 同樣, int &不能綁定到int&& ,但bool可以,因此它調用第二個 function。

同樣的推理也適用於您的示例,但是我刪除了variant和自定義重載集,因為它簡化了情況,而沒有改變潛在的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM