The following small C++ program involving a call to the template function std::atomic_fetch_add()
fails to compile in godbolt for x86-64 clang versions less than 9.0 and gcc versions less than 9.1,
in both cases using the --std=c++11
option.
#include <iostream>
#include <atomic>
std::atomic<char> ch ('@');
int main ()
{
std::atomic_fetch_add (&ch, 5);
std::cout << ch << std::endl;
}
In those early compiler versions (it might be more related to the C++ libraries provided by the compilers, I'm not sure), the std::atomic_fetch_add (&ch, 5);
call fails to match any template specialization for the atomic fetch function, since the type of ch
is char
, and the type of 5
is int
:
: In function 'int main()': :8:34: error: no matching function for call to 'atomic_fetch_add(std::atomic*, int)' std::atomic_fetch_add (&ch, 5); ...
However, later versions of the compiler (& libraries?) successfully compile this usage.
- What changed to make this start compiling?
- If it is a standard library change, what technique is used to allow this?
- Does the C++ standard (& what version?) require that this usage should work.
I'm pretty much a C++ beginner, but I gather that this is related to implicit conversions not being performed as part of figuring out the appropriate template specialization to use. (I may not be using precise language.)
I know that I can modify the call to work by rewriting it as either
std::atomic_fetch_add<char> (&ch, 5);
or
std::atomic_fetch_add (&ch, (char)5);
However, I'm interested in getting a version of the <atomic>
library to support the usage without the explicit instantiation and without the cast. (The compiler is clang 15.0.0, --std=c++11
. The library is a proprietary version of the Dinkum libraries.)
I need to understand how to support the calling of template functions like
std::atomic_fetch_char (&ch, 5)
where the argument types do not exactly match those in the template declaration. I would, for example, like to understand how this is supported in the linux /usr/include/c++/11/
standard library.
The nearest I've come up with myself is to add non-template overloads of various instantiations of std::atomic_fetch_add()
& similar functions, but I don't see that being done in the Linux/GNU C++ libraries and I suspect there is a cleaner way. I want to understand it.
std::atomic_fetch_add
have been retroactively changed in the C++11 standard because of defect report P0558R1. – Varistor