"Uses std :: begin"; good practice?
As I read it begin(some_vector)
is more standard than some_vector.begin()
because of array support ... and as I know usage is using keyword
not really the desired behavior. However, I also see a lot of code that only contains these two usings
:
using std::begin;
using std::end;
Is this considered good or bad practice? Especially when it takes a lot begin
and end
?
source to share
As I read
begin(some_vector)
is more standard thansome_vector.begin()
array support
This is not "more standard", both are 100%. It's more general because it works for arrays, but it's really not very common to have an object and not know if it's an array or a container type. If you have what you know is an array, then use it std::begin(a)
, but if you have something that you know is not an array, then there is no advantage to using a form that also works with arrays. If you are in a general context where you have, then it std::begin
works for both cases.
using a keyword is
using
not desirable behavior.
It's debatable. There are very good reasons to avoid using directives in most contexts (i.e. using namespace foo
), but the same arguments do not apply to declarations that introduce the same name (i.e. using foo::bar
). For example, the recommended way to use std::swap
is via using std::swap
, so it is of course not true that the keyword is using
generally undesirable.
Is this considered good or bad practice? Especially when you need a lot of beginning and end?
I would say that overall this is a bad idea. As other answers explain, it allows begin
and end
find ADL, but that's not necessarily good. Enabling ADL for begin
and end
can cause problems, so we changed based on the range for
at the last minute to not use using std::begin; using std::end;
to avoid ambiguity, see N3257 for details.
source to share
This might be helpful for reference ADL
. Something like:
template<typename T, typename F>
void apply(T& v, const F& f)
{
using std::begin;
using std::end;
std::for_each(begin(v), end(v), f);
}
So, we can just call apply
with types that have functions begin/end
and classic C arrays.
Otherwise, it is actually ok to use the directive using
in the source file, in a small amount, etc., but it is bad to use it in the header.
source to share
Is this considered good or bad practice?
This is highly context dependent; I think the answer applies equally to the more general question of naming through using
. Limit the scope of use using
makes the code more readable (for example, the scope of the function level); use it as needed, use it with care.
A particularly interesting case here revolves around ADL.
template <class Container>
void func(Container& c)
{
std::for_each(begin(c), end(c), /* some functor*/);
}
ADL is already in the game, as if the container is of the namespace std
to be found std::begin
and std::end
. If the container is from a custom namespace, functions begin
and can be found in that namespace end
(for this discussion, I am assuming the container vendor has provided them as well).
If the container is a regular C-style array, the shape of the array std::begin(T (&array)[N])
will not be found because the C-style array is not a namespace std
. The view using std::begin
here allows code to be used for arrays and containers.
template <class Container>
void func(Container& c)
{
using std::begin; // if c is an array, the function will still compile
using std::end;
std::for_each(begin(c), end(c), /* some functor*/);
}
// ...
int a[100];
func(a); // works as expected
Demo .
source to share
It depends. The use of declarations (and indeed the use of directives) in header files is pretty much discouraged. However, if you use one or more functions from a different namespace inside the function body many times, using declarations / directives (placed inside the function body, limited by its scope) can make the code more readable.
source to share