`std::back()` like function in C++
Asked Answered
S

3

6

I can create begin and end iterators using std::begin() and std::end().
e.g:

int arr[4][4] = <something here>;
auto begin_it = std::begin(arr);
auto end_it = std::end(arr);

However, why do we not have std::front() and std::back(). Is there any specific reason for them to be ommitted?

Are there any similar functions I can use (apart from begin and end of course)?

Scarab answered 26/8, 2020 at 3:7 Comment(4)
How often do you need to use those on arrays? You use begin/end/size all the time (or the alternatives they replace).Herd
Not sure about a reason to omit them, probably just no reason to include those functions. If you want them for some reason, you could just write your ownInterest
My opinion is front would cause UB frequently on empty or not defined front container but begin would not cause that as long as it's not dereferenced.Demon
@LouisGo, but they could have vaildated that, couldn't they?Scarab
D
3

Is there any specific reason for them to be ommitted?

Is there any specific reason for them to be included?

Things are not thrown into the standard library just because they can be. The standard library is intended to consist of useful functions, templates, and the like. The "burden of proof" lies with the person who wants something included. It's only after a use-case has been established, presented to the standards committee, and dismissed by said committee that it would be accurate to call the something "omitted".

That being said, there are several potential reasons for something not be included in the standard library, and "not useful" is only one of these. Other potential reasons include "implementation not good enough across all platforms" and "oh, we didn't think of that". While I do not know which reason applies here, I can provide some food for thought by comparing std::end() to a hypothetical std::back().

One can use std::end() with a C-style array (of known size) or anything meeting the requirements of "Container", such as all containers in the standard library. It has great utility in looping over containers, which is a reasonably common operation. A result of adding std::end() to the standard library is that many of the algorithms of the standard library no longer need template specialization to handle C-style arrays. (Admittedly, range-based for loops had a similar effect.)

One would be able to use std::back() with a C-style array (of known size), a std::array, or anything meeting the requirements of "SequenceContainer", such as strings, vectors, deques, lists, and forward lists (and nothing else from the standard library). It has utility in... um... I'm drawing a blank, but I'll grant the possibility of a general use for back(), although probably nowhere close to being as common as looping.

Since std::back() would be applicable in fewer situations than std::end(), it might have been overlooked. At the same time, since std::back() would be applicable in fewer situations than std::end(), it might not meet the "useful" criteria for being included in the standard library.

Are there any similar functions I can use (apart from begin and end of course)?

You could switch from C-style arrays to std::array, then use std::array::back(). After all, std::array is just a C-style array wrapped up to look like a contiguous sequence container. The type declaration is longer, but the functions you are looking for become readily available.

The standard library has a goal of supporting C-style arrays because it is a library, destined to be used by code the library's authors never dreamt of. If you're not writing a library, you probably don't really need to support C-style arrays.

Denning answered 26/8, 2020 at 4:29 Comment(0)
C
5

Not all containers have constant-time access to the last element of the list.

std::forward_list for example.

Crary answered 26/8, 2020 at 3:21 Comment(0)
D
4

Just like Marshall Clow said, inconsistent access time across containers should be considered.

My opinion is front would cause UB frequently on empty or not defined front container but begin would not cause that as long as it's not dereferenced.

std::vector v;
auto item = std::front(v); // This line immediately cause undefined behavior.

If std::front exists, it might cause more problems than the convenience it brings.

Because every call of front must come after empty. Then that's two function calls to make it convenient..

std::vector v;
// ...
if( !v.empty() ){
    auto item = std::front(v);
    // ...tasks
}

HMM.. Is it convenient? While programmer could get front consciously by *begin(container) and use it before check. All we saved is just an asterisk.

std::vector v;
// ...
if( !v.empty() ){
    auto item = *std::begin(v); 
    // ...tasks
}
Demon answered 26/8, 2020 at 3:30 Comment(1)
I think we already have the second: std::emptyHerd
D
3

Is there any specific reason for them to be ommitted?

Is there any specific reason for them to be included?

Things are not thrown into the standard library just because they can be. The standard library is intended to consist of useful functions, templates, and the like. The "burden of proof" lies with the person who wants something included. It's only after a use-case has been established, presented to the standards committee, and dismissed by said committee that it would be accurate to call the something "omitted".

That being said, there are several potential reasons for something not be included in the standard library, and "not useful" is only one of these. Other potential reasons include "implementation not good enough across all platforms" and "oh, we didn't think of that". While I do not know which reason applies here, I can provide some food for thought by comparing std::end() to a hypothetical std::back().

One can use std::end() with a C-style array (of known size) or anything meeting the requirements of "Container", such as all containers in the standard library. It has great utility in looping over containers, which is a reasonably common operation. A result of adding std::end() to the standard library is that many of the algorithms of the standard library no longer need template specialization to handle C-style arrays. (Admittedly, range-based for loops had a similar effect.)

One would be able to use std::back() with a C-style array (of known size), a std::array, or anything meeting the requirements of "SequenceContainer", such as strings, vectors, deques, lists, and forward lists (and nothing else from the standard library). It has utility in... um... I'm drawing a blank, but I'll grant the possibility of a general use for back(), although probably nowhere close to being as common as looping.

Since std::back() would be applicable in fewer situations than std::end(), it might have been overlooked. At the same time, since std::back() would be applicable in fewer situations than std::end(), it might not meet the "useful" criteria for being included in the standard library.

Are there any similar functions I can use (apart from begin and end of course)?

You could switch from C-style arrays to std::array, then use std::array::back(). After all, std::array is just a C-style array wrapped up to look like a contiguous sequence container. The type declaration is longer, but the functions you are looking for become readily available.

The standard library has a goal of supporting C-style arrays because it is a library, destined to be used by code the library's authors never dreamt of. If you're not writing a library, you probably don't really need to support C-style arrays.

Denning answered 26/8, 2020 at 4:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.