By L. F.


2019-04-15 10:20:12 8 Comments

Consider the following code:

#include <cctype>
#include <functional>
#include <iostream>

int main()
{
    std::invoke(std::boolalpha, std::cout);               // #1
    std::cout << std::invoke(std::tolower, 'A') << "\n";  // #2
}

Here, the two calls to std::invoke are labeled for future reference. The expected output is:

a

Is the expected output guaranteed?

1 comments

@L. F. 2019-04-15 10:20:12

Short answer

No.

Explanation

[namespace.std] says:

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. [Note: Possible means of forming such pointers include application of the unary & operator ([expr.unary.op]), addressof ([specialized.addressof]), or a function-to-pointer standard conversion ([conv.func]). —‚ÄČend note ] 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.

With this in mind, let's check the two calls to std::invoke.

The first call

std::invoke(std::boolalpha, std::cout);               // #1

Here, we are attempting to form a pointer to std::boolalpha. Fortunately, [fmtflags.manip] saves the day:

Each function specified in this subclause is a designated addressable function ([namespace.std]).

And boolalpha is a function specified in this subclause. Thus, this line is well-formed, and is equivalent to:

std::cout.setf(std::ios_base::boolalpha);

But why is that? Well, it is necessary for the following code:

std::cout << std::boolalpha;

The second call

std::cout << std::invoke(std::tolower, 'A') << "\n";  // #2

Unfortunately, [cctype.syn] says:

The contents and meaning of the header <cctype> are the same as the C standard library header <ctype.h>.

Nowhere is tolower explicitly designated an addressable function.

Therefore, the behavior of this C++ program is unspecified (possibly ill-formed), because it attempts to form a pointer to tolower, which is not designated an addressable function.

Conclusion

The expected output is not guaranteed. In fact, the code is not even guaranteed to compile.

@lubgr 2019-04-15 10:32:16

Related, interesting read (though this article doesn't touch on the concept of an addressable function).

@L. F. 2019-04-15 10:33:54

@lubgr Good point! It should suffice in general.

@zwol 2019-04-15 17:24:04

It is interesting to observe that the C standard takes exactly the opposite perspective: N1570 7.1.4 "...unless explicitly stated otherwise in the detailed descriptions...it is permitted to take the address of a library function." (setjmp is an example of a C library function whose address may not be taken, see 7.13p3.)

@L. F. 2019-04-16 09:37:45

Good to know! This shows that C++ is quite defensive in library usage ;-)

Related Questions

Sponsored Content

23 Answered Questions

[SOLVED] Is there a standard sign function (signum, sgn) in C/C++?

  • 2009-12-14 22:27:15
  • batty
  • 306425 View
  • 362 Score
  • 23 Answer
  • Tags:   c++ c math

4 Answered Questions

5 Answered Questions

2 Answered Questions

[SOLVED] C++ Array out of Range access to calculate pointer valid?

2 Answered Questions

[SOLVED] Capturing a reference by reference in a C++11 lambda

6 Answered Questions

[SOLVED] Why do std::shared_ptr<void> work

11 Answered Questions

[SOLVED] Why is f(i = -1, i = -1) undefined behavior?

0 Answered Questions

Is it safe to use standard library functions before main() has been called?

  • 2016-06-30 12:55:08
  • Ruslan
  • 123 View
  • 4 Score
  • 0 Answer
  • Tags:   c++

2 Answered Questions

[SOLVED] Why does assigning to a reference to std::ostream fail to compile?

  • 2011-08-02 09:23:27
  • Johnas
  • 881 View
  • 9 Score
  • 2 Answer
  • Tags:   c++ ostream

Sponsored Content