1

Why I can't take the address of the std::addressof when I explicitly specify the type?

To make it more weird, when I c/p the implementation from 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;
}

note: I know it may be illegal to do this, since function is in std::, but I care about language/implementation limitations, not UB since I am doing something evil.

NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277

3 Answers3

3

As you already hinted yourself, taking the address of std::addressof has unspecified behavior, and so may or may not work, because it is not designated as an addressable function in the standard.

More practically speaking though, the issue is that there are at least two overloads for std::addressof, both being templates with one template parameter.

One taking T& as a function parameter and the other taking const T&& as a function parameter (where T is the template parameter). The latter is defined as delete'd.

std::addressof<int> is not sufficient to decide which of these to choose.

The library implementation could also choose to implement these specified overloads in different ways, or add additional overloads, which is why taking the address is unspecified.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
user17732522
  • 53,019
  • 2
  • 56
  • 105
  • ah... quite funny that one is deleted, but that kicks in after the selection is done, so it does not help, at least that is what I understand – NoSenseEtAl Mar 07 '22 at 16:21
  • 3
    @NoSenseEtAl Yes, it still takes part in overload resolution and is meant to prevent taking the address of a temporary (rvalue). – user17732522 Mar 07 '22 at 16:21
3

You should not use pointers to functions in the standard library unless they are addressable functions.

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.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
2

You are not specifying the type explicitly like you claim in the question. You are only supplying a template argument.

Try actually specifying the type explicitly:

int* (*fn_a)(int&) = &std::addressof<int>;
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • I meant that stuff inside < > should be enough to make the function unique, but as mentioned by you and accepted answer that is not unique. – NoSenseEtAl Mar 07 '22 at 17:17
  • While this solution solves the problem, it doesn't really explain what the cause of the problem is - the fact that `std::addressof` is overloaded, so you have to specify the type of which overload you want. See [C++ address of overloaded function](https://stackoverflow.com/questions/45146522/) – Remy Lebeau Mar 07 '22 at 21:14
  • @RemyLebeau That's true, I tailored the answer to the knowledge level of the question, which already stated that the type needed to be explicitly specified, but provided code that didn't actually do so. – Ben Voigt Mar 08 '22 at 16:43