为什么我不能获取 std::addressof 函数的地址

Why I can't take address of the std::addressof function

为什么我在明确指定类型时无法获取 std::addressof 的地址?

为了让它更奇怪,当我 c/p 来自 cppreference I can take address of that function 的实现时

#include <memory>

template<typename T>
void templ_fn();


template<class T>
typename std::enable_if<std::is_object<T>::value, T*>::type  xaddressof(T& arg) noexcept
{
    return reinterpret_cast<T*>(
               &const_cast<char&>(
                   reinterpret_cast<const volatile char&>(arg)));
}
 
template<class T>
typename std::enable_if<!std::is_object<T>::value, T*>::type xaddressof(T& arg) noexcept
{
    return &arg;
}

int main() {
    auto fn_1 = xaddressof<int>; // works
    (void) fn_1;
    auto fn_a = std::addressof<int>; // does not work
    (void) fn_a;
}

注意:我知道这样做可能是非法的,因为函数在 std:: 中,但我关心 language/implementation 限制,而不是 UB,因为我在做坏事。

正如您已经暗示过的那样,获取 std::addressof 的地址具有未指定的行为,因此可能会或可能不会工作,因为它未指定为 可寻址函数 在标准中。

但更实际地说,问题是 std::addressof 至少有两个重载,都是具有一个模板参数的模板。

一个以T&作为函数参数,一个以const T&&作为函数参数(其中T为模板参数)。后者定义为delete'd.

std::addressof<int> 不足以决定选择哪一个。

库实现还可以选择以不同的方式实现这些指定的重载,或者添加额外的重载,这就是获取地址未指定的原因。

您不应使用指向标准库中函数的指针,除非它们是可寻址函数。

namespace.std#6:

Let F denote a standard library function ([global.functions]), a standard library static member function, or an instantiation of a standard library function template. Unless F is designated an addressable function, the behavior of a C++ program is unspecified (possibly ill-formed) if it explicitly or implicitly attempts to form a pointer to F.

您没有像您在问题中声称的那样明确指定类型。您只提供了一个模板参数。

尝试明确指定类型:

int* (*fn_a)(int&) = &std::addressof<int>;