msvc 编译器(和其他编译器)如何知道要绑定到哪个 std 重载?

How does msvc compiler(and other compilers) knows which std overload to bind to?

我知道这个问题有两个答案——一个很长很复杂,一个很短很简单。目前,我对后者感兴趣。

我来自 C#/.NET 背景,如果你使用它一段时间(或 Java)你可能会同意我的观点,无论何时你使用一些 BCL class 或方法是相对容易推断为什么编译器选择了某些重载。

C# 的简单示例

// lets imagine we have this somewhere in our code
Contract.Requires(e != null);

// we check who implements this method ...

public static void Requires(bool condition); // <-- observing the call its pretty obvious that this method will be chosen instead of the others
public static void Requires<TException>(bool condition, string userMessage) where TException : Exception;
public static void Requires<TException>(bool condition) where TException : Exception;
public static void Requires(bool condition, string userMessage);

如果你还没有弄明白我还在努力学习 C++,那么我会举一个简单的例子,希望在这个问题之后我会开始感觉更舒服地阅读标准代码。

// we have this call
int ints[5];
std::is_heap(std::begin(ints), std::end(ints));

// first method I tried to unwind was std::begin and std::end
// and this is what I got from Visual Studio as suggestion (and later confirmed by runtime)

template <class _Ty, size_t _Size>
_NODISCARD constexpr _Ty* begin(_Ty (&_Array)[_Size]) noexcept {
    return _Array;
}

template <class _Ty, size_t _Size>
_NODISCARD constexpr _Ty* end(_Ty (&_Array)[_Size]) noexcept {
    return _Array + _Size;
}

// then I checked std::is_heap and I got

template <class _RanIt>
_NODISCARD bool is_heap(_RanIt _First, _RanIt _Last) { // test if range is a heap ordered by operator<
    return _STD is_heap(_First, _Last, less<>());
}

我想我会在做出一些假设之前提醒您我的免责声明,即我是 C++ 的新手。

  1. (&_Array)[_Size] 是否有某种方法可以帮助编译器理解传递给某个函数(或函数模板)的参数将是数组(类似于 type_traits)?
  2. 在第二个静态绑定 (std::is_heap) 中,是不是因为模板是编译时的,因此建议的函数看起来不像您期望的那样,例如,某种 is_heap(int*, int*) 因为这些是你调用它的参数类型?

Is (&_Array)[_Size] some way of helping compiler understand that parameter passed to a certain function (or function template) will be array (something like type_traits)?

_Ty (&_Array)[_Size] 是一个数组参数 (a _Ty[_Size]),通过引用传递并命名为 _Array。信不信由你,C 看起来很奇怪。与类型特征无关。

我不太明白你的第二个问题,但编译器会选择最符合你的参数的重载。关于 "best" 的含义的规则很复杂,但在标准中有描述。如果多个重载均等匹配,则您的调用不明确,程序将无法编译。模板确实使这一点变得复杂,因为它们根据其本质引入了许多 可能的候选人。我同意模板很可能在此处用 _RanIt=int* 实例化,结果与您的调用完美匹配。