ADL fails when there are lambda arguments? - c++

quite some time ago i noticed that in Visual C++ 10 ADL fails when at least one of the arguments is a lambda.
std::vector<float> vec;
for_each(begin(vec), end(vec), [](float) {});
The above fails to compile on VC++10 and 11 (beta) (begin and end are found via ADL). When i convert the lambda function into a regular free function things work just as expected.
I've asked on Herb Sutters blog once and also read some posts on msdn connect and the usual answers were: this is a bug, we havent implemented the latest standard of the lambdas yet which - at that time - was quite understandable. Things haven't been in a baked form yet. On MS connect there have also been disturbing comments that this will not be resolved for the next release i.e. vc 11.
My question is, is this code expected to work under the C++11 standard? I cant quite figure that out. Do i really have to prefix my for_each and other algorithms with std:: when I'm using lambdas?
I somehow suspect that this behavior will not change after vc++11 release.

The standard doesn't guarantee what you'd want it to..
With the below in mind we can easily realize that there is nothing guaranteeing that ADL would work in cases similar to the example provided in your post.
std::begin (c)/std::end (c)
The functions are described in the standard as the below quotation:
template <class C> auto begin(C& c) -> decltype(c.begin());
template <class C> auto end(C& c) -> decltype(c.end());
Though the Container< ... >::iterator (which is the return-type of c.begin ()) is an implementation-defined type.
More about the matter can be read upon at 24.5.6 Range Access, and 23.3.6.1/2 class template vector (or any other template STL container).
[](){} - Lambda Expressions
A lambda is an implementation-defined type, there is nothing in the standard stating that the resulting object will be of a type which is under namespace std.
It can pretty much exists wherever it wants, as long as it confirms to the other rules set up by the standard.
Too Long; Didn't Read
The types of which std::begin/std::end/a lambda-expression yields are not guaranteed to be under namespace std, therefore ADL is not guaranteed to kick in.

That is perfectly valid code. Any bug-free compiler will be able to compile it. But since MSVC has bug and so is unable to search the function through ADL, then maybe you should not rely on ADL and instead qualify it with std:: helping the compiler to find the function.

Related

Is the c++ code in standard library all valid c++?

Just out of curiosity, I looked at how std::is_pointer is implemented and saw stuff like this (one of multiple overloads):
template <class _Ty>
_INLINE_VAR constexpr bool is_pointer_v<_Ty*> = true;
which if I copy and paste into my code and compile says constexpr is not valid here. What is happening?
Is it possible to implement structs like std::is_pointer and std::is_reference by us? (Not that I would, just curious so please don't come at me)
MRE with msvc 2019:
template <class _Ty>
inline constexpr bool is_pointer_v<_Ty*> = true;
int main()
{
}
--
Error: error C7568: argument list missing
after assumed function template 'is_pointer_v'
To answer the question in the title:
No, standard library code does not need to adhere to the language rules for user code. Technically it doesn't even need to be implemented in C++, but could e.g. be directly integrated into the compiler.
However, practically the standard library code is always compiled by the compiler just as user code is, so it will not use any syntax constructs that the compiler would reject for user code. It will however use compiler-specific extensions and guarantees that user code should not generally rely on. And there are also some reservations made specifically to the standard library implementation in the standard.
For example, the snippet you are showing from the standard library implementation is not valid user code, because _Ty is a reserved identifier that may not be used by user code, because it starts with an underscore followed by an uppercase letter. Such identifiers are specifically reserved to the standard library implementation. For this reason alone most standard library code will not be valid user code.
You are using a partial template specialization here. You need a complete declaration of the template to get that code to compile, like this:
template <class _Ty>
inline constexpr bool is_pointer_v = false;
template <class _Ty>
inline constexpr bool is_pointer_v<_Ty*> = true;
See here for example code
To answer your questions, the STL implementation requires specific C++ primitives that the compiler implements to support the required API. You can't have a constexpr version of the STL if the compiler does not implement it.
It's not possible to implement the complete STL without some compiler specifics code and the operating system's primitives. This is different from system to system (you can't use the STL implementation of linux on windows for example). It relies on undefined behavior, and many optimization which are known to be right for that specific compiler.
For example, you can't implement type punning (i.e converting from float* to int* and dereferencing) without UB in C++ (see here and here)
You have to rely on memcpy, but that can't be implemented without UB code (that is well defined if you write the compiler, BTW), since memcpy is accessing the memory likely not in the initial type that it's declared.
Yet, you can always copy & paste the STL code from your system and it'll always build correctly on your compiler.

Is this a valid way of performing "Expression SFINAE" in C++03?

In C++11, it is easy to SFINAE on whether or not an expression is valid. As an example, imagine checking if something is streamable:
template <typename T>
auto print_if_possible(std::ostream& os, const T& x)
-> decltype(os << x, void());
print_if_possible will only participate in overload resolution if os << x is a well-formed expression.
live example on godbolt.org
I need to do the same in C++03, and I figured out that sizeof could help (as I needed an unevaluated context for an expression). This is what I came up with:
template <int> struct sfinaer { };
template <typename T>
void print_if_possible(std::ostream& os, const T& x,
sfinaer<sizeof(os << x)>* = NULL);
live example on godbolt.org
It seems that both the latest versions of g++ and clang++ accept the sizeof version with -std=c++03 -Wall -Wextra.
Is the code guaranteed to work as intended in C++03?
Is it correct to conclude that any usage of C++11 expression SFINAE can be backported to C++03 using sfinaer and sizeof?
Expression SFINAE is a bit gray. C++03 basically said nothing on the subject. It neither explicitly banned it nor explicitly allowed it. Contemporary implementations did not permit such constructs because it caused substantial implementation complexity and it's unclear whether it's meant to be allowed, and CWG was at one point leaning towards banning it (see the April, 2003 note) before it eventually reversed course, partially in light of decltype and constexpr that were added to C++11 (see the introduction to N2634).
This also all happened well before CWG started explicitly marking the DR status of issues whose resolutions are meant to apply retroactively.
I think the best advice here is simply "ask your compiler vendor". A compiler that supports expression SFINAE in its C++11 mode is unlikely to tear out that support in C++03 mode (the vendor may treat CWG 339 as a defect report and apply it retroactively, or consider it as an extension). OTOH, a compiler that never supported C++11 is unlikely to invest the substantial costs necessary for expression SFINAE to work (indeed, it did not work in a certain major compiler cough until relatively recently). I also suspect that a place still stuck with an 15-year-old language is unlikely to use the modern toolchains necessary for such support.

Why all function in <cstring> must not have constexpr?

I just noticed that D0202R2 propose that all <cstring> functions must not have constexpr. I would like to understand why, during Jacksonville meeting, it was decided for a solution like this.
Take a function like std::strchr. I really do not see any reason for not being constexpr. Indeed, a compiler can easily optimize some dummy code like this at compile-time (even if I remove builtins, as you can see from the parameters). However, at the same time, it is not possible to rely on these functions within constexpr contexts or using static assertions.
We could obviously re-implement some of <cstring> functions to be constexpr (as I did in this other dummy code), but I do not understand why they must not have constexpr in the standard library.
What am I missing?
PS: Builtins!
At the beginning I was confused because constexpr functions using some <cstring> capabilities just worked, then I understood it was only thanks to GCC builtins. Indeed, if you add the -fno-builtin parameter, you can just use std::strlen instead of the custom version of the function.
Upon reviewing this more, and thinking more about the implications of the C++14 relaxation of rules surrounding constexpr, I have a different answer.
The <cstring> header is a wrapper around a bunch of C functions. C has no constexpr concept, and while it might be useful for it to have one, it's not likely to grow one anytime soon. So marking up those functions in that way would be cumbersome and require a lot of #ifdefs.
Also (and I think this is the most important reason) when those functions are not compiler intrinsics they are implemented in C and stored in a library file as object code. Object code in a library is not a form accessible to the C++ compiler to evaluate at compile time. They are not 'inline' like template code is.
Lastly, most of the really useful things they do can easily be implemented in terms of the C++ <algorithm> library. strlen(s) = (::std::string_view(s)).length(), memcpy(a, b, len) = ::std::copy(b, b + len, a) and so on. And D0202R2 proposes to make those algorithms constexpr. And, as you pointed out, it also proposes to make functions in ::std::string_view constexpr and these also give equivalent functionality. So, given the previously mentioned headaches, it seems that implementing constexpr for the <cstring> functions would be of dubious benefit.
As a side note, there's ::std::copy, ::std::move, ::std::copy_backward, and ::std::move_backward and it's up to you to figure out which you need to call. It would be nice if there was a function that could figure out whether or not x or x_backward was needed in that particular case like memmove does. But, because of the way iterators are defined, taking one iterator and comparing it to another iterator that may not be iterating over the same object at all just isn't possible to do in C++, even if they're random access iterators.

What SFINAE tricks can I safely use on all MSVC >= 2013?

In Qt I had the brilliant (cough, cough) idea to start defining overloads of qHash (the hashing function used for QHash, one of Qt's associative containers) for Standard Library datatypes: std::basic_string, std::shared_ptr and the like.
There could be a shortcut for this process: instead of chasing "any Standard Library type that could be used as a key in QHash" and adding a qHash overload for it, I could just define qHash automatically if the type has a std::hash specialization for it (reasonably assuming that we don't want to do more than what the Standard Library does in this process).
That is, I could implement something like this using expression SFINAE:
template<typename T>
auto qHash(const T &t) -> decltype(std::hash<T>()(t))
{
return std::hash<T>()(t);
}
Unfortunately, although Qt demands a C++11 compiler, expression SFINAE is not allowed anywhere because MSVC does not fully support it (at the time of this writing: all MSVC versions, up to and including VS15 preview 5. Anyhow, Qt must support all the way back to 2013).
Hence, the question: is there a way to do the same, in a way that
does not use expression SFINAE
is guaranteed to work on all MSVC versions >= 2013?
I was thinking a plain good ol' C++98 SFINAE construction via enable_if and the like, but other SO answers (like this one) make me think that MSVC 2013 may miscompile that too, so the result becomes unacceptable again.
I do not think you need expression SFINAE for this, something along these lines should work.
template<typename T>
typename std::hash<T>::result_type qHash(const T &t)
{
return std::hash<T>()(t);
}
Or pretty much any approach that does SFINAE on hash::result_type. Unfortunately for you, hash::result_type is deprecated in C++17, but you can still #ifdef this code for MSVC 2013.

VS 11 with std::future - Is this a bug?

I recently installed the Visual Studio 11 Developer Preview. While playing with threads and futures, I came around this setup:
#include <future>
#include <iostream>
int foo(unsigned a, unsigned b)
{
return 5;
}
int main()
{
std::future<int> f = std::async(foo, 5, 7);
std::cout << f.get();
}
So, very simple. But since there are two arguments for "foo", VS 11 doesn't want to compile it. (However, g++ does: http://ideone.com/ANrPj) (The runtime error is no problem: std::future exception on gcc experimental implementation of C++0x) (VS 11 errormessage: http://pastebin.com/F9Xunh2s)
I'm a little confused right now, since this error seems extremely obvious to me, even if it is a developer preview. So my questions are:
Is this code correct according to the C++11 standard?
Is this bug already known/reported?
std::future is supposed to be a variadic template. This is what allows you to pass an arbitrary number of arguments to the function being invoked asynchronously.
Unfortunately, the current preview of VS 11 doesn't support variadic templates, which means it doesn't have the mechanism for you to pass more than one argument to the function.
Bottom line: VS is wrong. I'm not sure if anybody has reported this as a bug, but it's a direct consequence of a fact that's already well known, so reporting it probably wouldn't/won't do a whole lot of good other than indirectly adding a vote that variadic templates are important.
If you look on the VC++ News page, they (currently) have a link to a survey that's supposed to allow you to indicate priorities you'd assign to conformance with various C++11 features. Unfortunately it seems to be offline, at least at the moment. When you can, filling it in to indicate that you consider variadic templates a high priority has at least some chance of doing some good for this (though I obviously can't guarantee anything).
Try below adhoc workaround. (I tried at Visual Studio 11 Beta)
std::future<int> f = std::async(std::launch::any, foo, 5, 7);
As C++11 standards function std::async() has two overloads, but MSVC/CRT can't do correct overload resolution. Furthermore std::launch::any is NOT a part of standard. (it requires std::launch::async|std::launch::deferred, but they can't compile again)