Style question
-
I have a C++ function that takes as argument an iterator and needs to increment it without passing the end of the container. I can write it as: variant A:
bool func (std::string::iterator& ptr, std::string& container)
{
//...
if (ptr != container.end())
//do stuff
}and call it as:
func (s.begin(), s);
or I could write it as variant B:
bool func (std::string::interator& ptr, std::string::const_iterator& limit)
{
//...
if (ptr != limit)
//do stuff
}and call it as:
func (s.begin(), s.end());
(the example assumes the container is a string but that's not important) Which one would you favor?
Mircea
-
I have a C++ function that takes as argument an iterator and needs to increment it without passing the end of the container. I can write it as: variant A:
bool func (std::string::iterator& ptr, std::string& container)
{
//...
if (ptr != container.end())
//do stuff
}and call it as:
func (s.begin(), s);
or I could write it as variant B:
bool func (std::string::interator& ptr, std::string::const_iterator& limit)
{
//...
if (ptr != limit)
//do stuff
}and call it as:
func (s.begin(), s.end());
(the example assumes the container is a string but that's not important) Which one would you favor?
Mircea
If the function modified the contents of the container I would probably pass it the container reference, otherwise I would prefer the iterators (or even a
std::span
). -
I have a C++ function that takes as argument an iterator and needs to increment it without passing the end of the container. I can write it as: variant A:
bool func (std::string::iterator& ptr, std::string& container)
{
//...
if (ptr != container.end())
//do stuff
}and call it as:
func (s.begin(), s);
or I could write it as variant B:
bool func (std::string::interator& ptr, std::string::const_iterator& limit)
{
//...
if (ptr != limit)
//do stuff
}and call it as:
func (s.begin(), s.end());
(the example assumes the container is a string but that's not important) Which one would you favor?
Mircea
-
If the function modified the contents of the container I would probably pass it the container reference, otherwise I would prefer the iterators (or even a
std::span
).Good points, thank you! However
std::span
is C++20 and I want to keep the code C++14.Mircea
-
The second one: give to the function the strict necessary for its task.
"In testa che avete, Signor di Ceprano?" -- Rigoletto
Yep, my thoughts exactly. Thank you!
Mircea
-
Yep, my thoughts exactly. Thank you!
Mircea
-
I have a C++ function that takes as argument an iterator and needs to increment it without passing the end of the container. I can write it as: variant A:
bool func (std::string::iterator& ptr, std::string& container)
{
//...
if (ptr != container.end())
//do stuff
}and call it as:
func (s.begin(), s);
or I could write it as variant B:
bool func (std::string::interator& ptr, std::string::const_iterator& limit)
{
//...
if (ptr != limit)
//do stuff
}and call it as:
func (s.begin(), s.end());
(the example assumes the container is a string but that's not important) Which one would you favor?
Mircea
I have a more or less strict rule i.e. to wit in particular to be specific namely things that act like pointers are passed via copy constructor not via reference since raw pointers are fundamental type objects so take up little space and a reference is a pointer anyway. I agree w/ the chap who suggested passing only what the function requires i.e. first, last iterators. Further at point of call the code is easier to understand its purpose as it passes only what the function requires also it just looks better and is easier to understand as fewer ideas/concepts are involved namely the one idea/concept "iterator" rather than the two ideas/concepts "iterator and container". Was there not a recent article in a recent CP newsletter discussing this very thing i.e. minimizing the number of ideas/concepts needed to understand any code?
-
I have a more or less strict rule i.e. to wit in particular to be specific namely things that act like pointers are passed via copy constructor not via reference since raw pointers are fundamental type objects so take up little space and a reference is a pointer anyway. I agree w/ the chap who suggested passing only what the function requires i.e. first, last iterators. Further at point of call the code is easier to understand its purpose as it passes only what the function requires also it just looks better and is easier to understand as fewer ideas/concepts are involved namely the one idea/concept "iterator" rather than the two ideas/concepts "iterator and container". Was there not a recent article in a recent CP newsletter discussing this very thing i.e. minimizing the number of ideas/concepts needed to understand any code?
meagreProgrammer wrote:
things that act like pointers are passed via copy constructor not via reference
Except that in my case the iterator needs to be changed by the function, hence I have to pass a reference.
Mircea
-
meagreProgrammer wrote:
things that act like pointers are passed via copy constructor not via reference
Except that in my case the iterator needs to be changed by the function, hence I have to pass a reference.
Mircea
Would it be too lengthy or tedious an explanation to explain the need to modify the iterator. I find such a need quite unusual and do not recall ever having to perform same.
-
Would it be too lengthy or tedious an explanation to explain the need to modify the iterator. I find such a need quite unusual and do not recall ever having to perform same.
No problem: the iterator is a pointer in a UTF-8 encoded string and the function (called
next
) has to advance to the next code point (1, 2, 3 or 4char
). If iterator is at end of string it doesn't advance. Although a very simple function, I had a number of design decisions to make: - How should I deal with improperly encoded UTF-8 strings? I decided to returnfalse
if the string is not properly encoded. - Should I just leave out the boundary check and just document it? I decided against as it would have been unsafe. And the last one I was asking about: For limit check, should I just pass the string or the end iterator.Mircea