Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I answer the question of whether a standard library function is an "addressable function"?

I've recently come across Can I take the address of a function defined in standard library? and was shocked by the fact that the answer is fundamentally No. I surely have written &std::someTemplClass<SomeConcreteType>::someMember in a few places at least, so I should review all of them, but how do I go about it?

From the relevant piece of the standard,

[…] Unless F is designated an addressable function, the behavior of a C++ program is unspecified […]

it feels like I have to search the standard for all the std::stuff to which I've applied & and look for the words "addressable function".

But how can I be sure I've looked at the correct page for a given std::stuff?

The linked answer surely makes two examples, but I still have some doubts.

For instance:

Moreover, the behavior of a C++ program is unspecified (possibly ill-formed) if it attempts to form a reference to F or if it attempts to form a pointer-to-member designating either a standard library non-static member function ([member.functions]) or an instantiation of a standard library member function template.

Does this mean that a standard library non-static member function and an instantiation of a standard library member function template are never an addressable function?

If that's the case, am I correct to understand that any occurrence of &std::someTemplClass<SomeConcreteType>::someNonStaticMemberFunc or even just &std::someClass::someMemberFunc passed to a higher order function, such as in these cases,

doStuff(someRange | ranges::views::filter(&std::optional<int>::has_value));
std::transform(v.begin(), v.end(),
               w.begin(),
               boost::bind( &std::string::c_str, boost::placeholders::_1 ) );

is wrong?

And what about it being in unevaluated context, e.g. decltype(&std::someTemplClass<SomeConcreteType>::someNonStaticMember)?


Please, don't tell me the answer is "you should read the standard end-to-end" :(

like image 203
Enlico Avatar asked Oct 27 '25 14:10

Enlico


2 Answers

There is a, hopefully complete and maintained, list of these addressable functions at

https://en.cppreference.com/w/cpp/language/extending_std#Addressing_restriction

The addressable functions are only such functions that are designed for the use case to be passed to other functions (usually as by-reference). These are (currently) all IO streams-related. So the list is pretty small.

Yes, there are no addressable member functions of standard library templates or addressable specializations of function templates.

All the examples you give are not addressable and therefore have unspecified behavior. It is not undefined behavior, so it isn't that bad. The risk is that it may not compile on a different compiler or (less likely) that it may choose the wrong overload/specialization of the function.

Whether the context is evaluated or not doesn't matter. This is a question of overload resolution to give the standard library writer leeway to implement functions with different overloads/templates than specified in the standard. Generally it is only guaranteed that standard library functions behave according to their specification in direct calls.

When passing standard library functions as higher order functions the way you are doing it, you should pass them indirected through a lambda, as e.g. implemented by BOOST_HOF_LIFT. Unfortunately there is currently no nicer syntax for that in the language.

Also consider that the same problem may apply to other libraries. If the library writer was to guarantee that functions are addressable in the sense of "addressable function" in the standard, then that will strongly restrict them when making changes to the library. They would need to commit to not change the overload set of library functions or evaluate such changes very carefully.

like image 62
user17732522 Avatar answered Oct 29 '25 06:10

user17732522


Cppreference has a list of addressable functions, and it contains only iostream manipulators.

I've checked the standard draft, and the only places where the word "addressable" appears (outside of its definition) are all here (so indeed only manipulators).

So yes, your examples are illegal.

Including in unevaluated context. The point of this rule is to be able to quietly add overloads and change their signatures, as long as the call syntax looks normal. If the function you pass to decltype(&foo) ends up overloaded, you'll get a compilation error.

like image 37
HolyBlackCat Avatar answered Oct 29 '25 05:10

HolyBlackCat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!