Humam Helfawi
Humam Helfawi

Reputation: 20264

Is "using std::begin;" a good practice?

As I have read, begin(some_vector) is more standard than some_vector.begin() because of array support... and as I know also, the use of using keyword is not really desirable behavior. However, I also see lot of code that contains just these two usings:

using std::begin;
using std::end;

Is that considered good or bad practice? Especially when many begin and end are needed?

Upvotes: 8

Views: 1821

Answers (4)

Jonathan Wakely
Jonathan Wakely

Reputation: 171263

As I have read, begin(some_vector) is more standard than some_vector.begin() because of array support

It's not "more standard", both are 100% standard. It is more generic, because it works for arrays, but it's not actually very common to have an object and not know whether it's an array or a container type. If you have something that you know is an array then use std::begin(a) but if you have something that you know is not an array then there is no advantage to using the form that also works with arrays. If you're in a generic context where you might have either, then std::begin works for both cases.

the use of using keyword is not really desirable behavior.

That's debatable. There are very good reasons to avoid using-directives in most contexts (i.e. using namespace foo) but the same arguments don't apply to using-declarations that introduce a single name (i.e. using foo::bar). For example the recommended way to use std::swap is via using std::swap so it's certainly not true that the using keyword is undesirable in general.

Is that considered good or bad practice? Especially when many begin and end are needed?

I would say that in general it's a bad idea. As the other answers explain, it allows begin and end to be found by ADL, but that's not necessarily a good thing. Enabling ADL for begin and end can cause problems, that's why we changed range-based for at the last minute to not use using std::begin; using std::end; to avoid ambiguities, see N3257 for the details.

Upvotes: 15

Niall
Niall

Reputation: 30605

Is that considered good or bad practice?

This depends a lot on the context; I think the answer is equally applicable to the more general question of introducing names via a using. Limit the scope of the use of using makes for more readable code (such as function level scope); use it as required, 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 play, since if the container is from the std namespace, the std::begin and std::end will be found. If the container is from a custom namespace, begin and end functions can be found in that namespace (for this discussion, I assume the container provider has also provided these).

If the container is a normal C-style array, the array form std::begin(T (&array)[N]) will not be found since the C-style array is not the std namespace. Introducing a using std::begin here allows the 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.

Upvotes: 5

ForEveR
ForEveR

Reputation: 55887

It can be helpful for ADL help. 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, than we just can call apply with types, that have begin/end functions and classic C arrays.

In other case it's actually okay to use using directive in source file, in little scope and so on, but it's bad to use in header.

Upvotes: 7

Paolo M
Paolo M

Reputation: 12757

It depends. Using declarations (and, far more, using directives) in header files are heavily discouraged. However, if inside the body of a function you use a lot of times one or several functions from another namespace, a using declaration / directives (put inside the body of the function, so limited to its scope) can make the code more readable.

Upvotes: 1

Related Questions