"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

?

+3


source to share


4 answers


As I read begin(some_vector)

is more standard than some_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.

+7


source


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.

+6


source


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 .

+3


source


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.

+1


source







All Articles