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.
CodePudding user response:
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.
CodePudding user response:
You should not use pointers to functions in the standard library unless they are addressable functions.
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.
CodePudding user response:
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>;