无法理解的с++编译器行为

问题描述 投票:0回答:1

也许我对 C++ 不太了解,但我发现 C++ 编译器的行为难以理解(在我看来是危险的)。

MSVC、g++ 和 Clang 的行为相同。

问:为什么函数

::a::f
f
内可见为
b::f(bool)

namespace a {

struct C {
    bool value;
    C(): value(false) {}
    C(C const &): value(false) {}
    explicit C(bool value): value(value) {}
};

inline C f(bool value) { return C(value); }

// why this function is visible as `f` inside `b::f(bool)`?
inline C f(C const &value) { return C(not value.value); }

}

namespace b {

inline bool f(::a::C const &value) { return value.value; }

inline bool f(bool value) {
#ifdef WORK_AROUND_PROBLEM
    return b::f(a::f(value));
#else
    // why `::a::f` is visible as `f` here?
    return f(a::f(value)).value;
#endif
}

}


int main(int, char **) {
    if (b::f(false) or (! b::f(true))) return 1;
    if (b::f(0)) return 2;
    if (b::f(a::C(false)) || (! b::f(a::C(true)))) return 3;
    return 0;
}

[更新] 用
Argument dependent lookup
解释。

https://en.cppreference.com/w/cpp/language/adl。感谢您的回答。 =)

c++ gcc visual-c++ g++ clang
1个回答
5
投票

这是由于参数依赖查找

如果函数采用自定义类型的参数,则在调用函数时会在声明该类型的命名空间中搜索可行的重载。

f(a::f(value))

正在将

C
传递给
f
。这会触发 ADL,因此除了在周围范围中进行名称查找之外,编译器还会在
namespace a
中搜索,因为
C
是在那里声明的。

这是定义自由函数运算符重载时最常见的重要特征。我们可以将它们放在与相关类型相同的命名空间中,

ADL
将确保在名称查找中找到重载,而不会污染全局/外部作用域。

© www.soinside.com 2019 - 2024. All rights reserved.