What's your preferred way of returning a list of items?

D

DeMarcus

Hi,

Here are a couple of ways to return some list of items.

struct A
{
};

std::vector<A> aList; // Some list of items.

// Returning a copy.
std::vector<A> getList() { return aList; }

void getList( std::vector<A>& v )
{
std::copy( aList.begin(), aList.end(), v.begin() );
}

void getList( std::vector<A>* v )
{
std::copy( aList.begin(), aList.end(), v->begin() );
}

// Returning a reference to aList.
const std::vector<A>& getList() { return aList; }

const std::vector<A>::const_iterator& getList()
{
return aList.begin();
}

Do you know more ways to return a list? What's your preferred way to
return a list of items?




Also, here comes another trickier one. Let's say I have a map instead
and want to return the keys.

std::map<std::string, A> aMap;

// Returning a copy of the keys.
std::vector<std::string> getList()
{
std::vector<std::string> aKeys;
auto keysEnd = aMap.end();
for( auto i = aMap.begin(); i != keysEnd; ++i )
aKeys.push_back( (*i).first );
return aKeys;
}

void getList( std::vector<std::string>& v )
{
auto keysEnd = aMap.end();
for( auto i = aMap.begin(); i != keysEnd; ++i )
v.push_back( (*i).first );
}

void getList( std::vector<std::string>* v )
{
auto keysEnd = aMap.end();
for( auto i = aMap.begin(); i != keysEnd; ++i )
v->push_back( (*i).first );
}


// But is it even possible to return a reference to
// the keys in a map?

const std::vector<std::string>& getList() { /* What here? */ }

const std::vector<std::string>::const_iterator& getList()
{
/* What here? */
}


How do you usually deal with these kind of list returns?



Thanks,
Daniel
 
K

Kai-Uwe Bux

DeMarcus said:
Hi,

Here are a couple of ways to return some list of items.

struct A
{
};

std::vector<A> aList; // Some list of items.

// Returning a copy.
std::vector<A> getList() { return aList; }

void getList( std::vector<A>& v )
{
std::copy( aList.begin(), aList.end(), v.begin() );
}

void getList( std::vector<A>* v )
{
std::copy( aList.begin(), aList.end(), v->begin() );
}

// Returning a reference to aList.
const std::vector<A>& getList() { return aList; }

const std::vector<A>::const_iterator& getList()
{
return aList.begin();
}

Do you know more ways to return a list? What's your preferred way to
return a list of items?

I often use output iterators. So, my function signature looks as follows:

template < typename OutIter >
OutIter get_items ( OutIter where, other args );

That way, the client can decide which data structure should be used when the
items are to be stored.
Also, here comes another trickier one. Let's say I have a map instead
and want to return the keys.

std::map<std::string, A> aMap;

// Returning a copy of the keys.
std::vector<std::string> getList()
{
std::vector<std::string> aKeys;
auto keysEnd = aMap.end();
for( auto i = aMap.begin(); i != keysEnd; ++i )
aKeys.push_back( (*i).first );
return aKeys;
}

void getList( std::vector<std::string>& v )
{
auto keysEnd = aMap.end();
for( auto i = aMap.begin(); i != keysEnd; ++i )
v.push_back( (*i).first );
}

void getList( std::vector<std::string>* v )
{
auto keysEnd = aMap.end();
for( auto i = aMap.begin(); i != keysEnd; ++i )
v->push_back( (*i).first );
}


// But is it even possible to return a reference to
// the keys in a map?

const std::vector<std::string>& getList() { /* What here? */ }

const std::vector<std::string>::const_iterator& getList()
{
/* What here? */
}


How do you usually deal with these kind of list returns?

See above.


Best

Kai-Uwe Bux
 
Ö

Öö Tiib

Hi,

Here are a couple of ways to return some list of items.

struct A
{

};

std::vector<A> aList;  // Some list of items.

// Returning a copy.
std::vector<A> getList() { return aList; }

void getList( std::vector<A>& v )
{
    std::copy( aList.begin(), aList.end(), v.begin() );

}

void getList( std::vector<A>* v )
{
    std::copy( aList.begin(), aList.end(), v->begin() );

}

// Returning a reference to aList.
const std::vector<A>& getList() { return aList; }

const std::vector<A>::const_iterator& getList()
{
    return aList.begin();

}

Do you know more ways to return a list? What's your preferred way to
return a list of items?

Also, here comes another trickier one. Let's say I have a map instead
and want to return the keys.

std::map<std::string, A> aMap;

// Returning a copy of the keys.
std::vector<std::string> getList()
{
    std::vector<std::string> aKeys;
    auto keysEnd = aMap.end();
    for( auto i = aMap.begin(); i != keysEnd; ++i )
       aKeys.push_back( (*i).first );
    return aKeys;

}

void getList( std::vector<std::string>& v )
{
    auto keysEnd = aMap.end();
    for( auto i = aMap.begin(); i != keysEnd; ++i )
       v.push_back( (*i).first );

}

void getList( std::vector<std::string>* v )
{
    auto keysEnd = aMap.end();
    for( auto i = aMap.begin(); i != keysEnd; ++i )
       v->push_back( (*i).first );

}

// But is it even possible to return a reference to
// the keys in a map?

const std::vector<std::string>& getList() { /* What here? */ }

const std::vector<std::string>::const_iterator& getList()
{
    /* What here? */

}

How do you usually deal with these kind of list returns?

Usually...

I avoid writing functions that are getters, copiers or even worse ...
setters, because these indicate lousy design. I usually try my best to
have interface that allows operations that make sense to do with the
objects of given type and not interface that allows mechanical
setting, getting and copying of the properties of objects.

My functions that are still getters are nouns (remove "get" prefix,
once situation enforces to be lousy, go maximum) and are either
returning copies or const references. My functions that fill their
parameters with a copy of internal data start with "copy" and i call
them copiers. Setters are also nouns (no "set" prefix; have to be java
so go maximum) but return void and take const reference as parameter.

I call std::vector as "a vector" and std::list as "a list". There are
no further deep reasons for such conventions; one just has to stick to
something over years.
 
A

Alf P. Steinbach

Hi,

Here are a couple of ways to return some list of items.

struct A
{
};

std::vector<A> aList; // Some list of items.

// Returning a copy.
std::vector<A> getList() { return aList; }

This one is OK, and will be efficient with modern compiler.

void getList( std::vector<A>& v )
{
std::copy( aList.begin(), aList.end(), v.begin() );
}

This one's signature is OK as an opt-in alternative to the first one (i.e.
provide /both/, or just the first one).

However, the implementation is incorrect unless you assume that the argument is
of exactly the right size for the result (and that assumption would be
unrealistic, to put it mildly).

You could write it like

void getList( std::vector< A >& v )
{
std::vector< A >( aList.begin(), aList.end() ).swap( v );
}


void getList( std::vector<A>* v )
{
std::copy( aList.begin(), aList.end(), v->begin() );
}

This one is just bad. Why would you want to support nullpointer argument? If
someone calls 'getList' it's in order to get that list, not in order to do nothing.

Anyway, under normal assumptions the implementation is incorrect.

// Returning a reference to aList.
const std::vector<A>& getList() { return aList; }

This one's OK if you're clear on what it does.


const std::vector<A>::const_iterator& getList()
{
return aList.begin();
}

This is one is just silly, the caller can't do anything reasonable with the
returned iterator.

Do you know more ways to return a list?

How about ways to return lists, instead of vectors (arrays)?



What's your preferred way to
return a list of items?

That doesn't make sense without a lot more explanation of exactly what you mean
by "list" and in what context you'd want to return -- what?

Also, here comes another trickier one. Let's say I have a map instead
and want to return the keys.

std::map<std::string, A> aMap;

// Returning a copy of the keys.
std::vector<std::string> getList()
{
std::vector<std::string> aKeys;
auto keysEnd = aMap.end();
for( auto i = aMap.begin(); i != keysEnd; ++i )
aKeys.push_back( (*i).first );
return aKeys;
}

void getList( std::vector<std::string>& v )
{
auto keysEnd = aMap.end();
for( auto i = aMap.begin(); i != keysEnd; ++i )
v.push_back( (*i).first );
}

void getList( std::vector<std::string>* v )
{
auto keysEnd = aMap.end();
for( auto i = aMap.begin(); i != keysEnd; ++i )
v->push_back( (*i).first );
}


// But is it even possible to return a reference to
// the keys in a map?

const std::vector<std::string>& getList() { /* What here? */ }

const std::vector<std::string>::const_iterator& getList()
{
/* What here? */
}

How about defining an iterator that walks through the keys. Then you don't have
to create all those string objects.

How do you usually deal with these kind of list returns?

Sorry, again the question is to vague to be meaningful to me.

But see above.


Cheers & hth.,

- Alf
(blog at <url: http://alfps.wordpress.com>)
 
D

DeMarcus

Öö Tiib said:
Usually...

I avoid writing functions that are getters, copiers or even worse ...
setters, because these indicate lousy design. I usually try my best to
have interface that allows operations that make sense to do with the
objects of given type and not interface that allows mechanical
setting, getting and copying of the properties of objects.

Ok, great. Actually I'm also very considered with clean design, but
sometimes I find it impossible to do anything else than returning a
container.

I'm playing around with a command in Linux called backtrace_symbols. The
command gives you the stack trace. Now I want to wrap that somehow and
this is what I've made so far.

std::vector<std::string> getStackTrace();

How would you do this? Like this

std::vector<std::string> stackTrace();

or provide functions that can be applied to the stack trace, e.g.

std::eek:stream& operator<<( std::eek:stream&, const StackTrace& );

or something else?
 
D

DeMarcus

Alf said:
This one is OK, and will be efficient with modern compiler.



This one's signature is OK as an opt-in alternative to the first one
(i.e. provide /both/, or just the first one).

However, the implementation is incorrect unless you assume that the
argument is of exactly the right size for the result (and that
assumption would be unrealistic, to put it mildly).

You could write it like

void getList( std::vector< A >& v )
{
std::vector< A >( aList.begin(), aList.end() ).swap( v );
}

That's nice! Where do I find tricks like that? I don't find such things
in Josuttis' book.
This one is just bad. Why would you want to support nullpointer
argument? If someone calls 'getList' it's in order to get that list, not
in order to do nothing.

I just listed all I could come to think of.

This one's OK if you're clear on what it does.




This is one is just silly, the caller can't do anything reasonable with
the returned iterator.



How about ways to return lists, instead of vectors (arrays)?

Lists are fine too, are there notable differences between returning a
vector and a list?

That doesn't make sense without a lot more explanation of exactly what
you mean by "list" and in what context you'd want to return -- what?

Here's an example I gave Öö Tiib.

I'm playing around with a command in Linux called backtrace_symbols. The
command gives you the stack trace. Now I want to wrap that somehow and
this is what I've made so far.

std::vector<std::string> getStackTrace();

How would you do that?

How about defining an iterator that walks through the keys. Then you
don't have to create all those string objects.

Please show, I need to enhance my skills. It feels right now that I'm
just using the basic methods.
 
S

Sousuke

Hi,

Here are a couple of ways to return some list of items.

struct A
{

};

std::vector<A> aList;  // Some list of items.

// Returning a copy.
std::vector<A> getList() { return aList; }

void getList( std::vector<A>& v )
{
    std::copy( aList.begin(), aList.end(), v.begin() );

Isn't that just a more complicated and unsafe way of doing:

v = aList;

?
}

void getList( std::vector<A>* v )
{
    std::copy( aList.begin(), aList.end(), v->begin() );

}

I recently started a thread on that subject (whether "out" parameters
should be pointers instead of references):

http://groups.google.com/group/comp.lang.c++/browse_thread/thread/697f5fbff47a94e3#

It seems most agreed that it's a dumb guideline.
// Returning a reference to aList.
const std::vector<A>& getList() { return aList; }

That's the preffered way if the object being returned is a member of a
class (which means that the method is just a simple accessor
(getter)). More generally, it's ok as long as the object's lifetime is
well-defined and known to the caller (in the case of a member
variable, the lifetime is the same as that of its containing object).
const std::vector<A>::const_iterator& getList()
{
    return aList.begin();

}

Seems pointless.
Do you know more ways to return a list? What's your preferred way to
return a list of items?

Either "vector<A> getList()" or "void getList(vector<A>&)" if I need
copying, or "const vector<A>& getList() const" (and possibly a non-
const overload) if the returned object is a member variable.
 
J

Jeff Flinn

DeMarcus said:
Ok, great. Actually I'm also very considered with clean design, but
sometimes I find it impossible to do anything else than returning a
container.

I'm playing around with a command in Linux called backtrace_symbols. The
command gives you the stack trace. Now I want to wrap that somehow and
this is what I've made so far.

std::vector<std::string> getStackTrace();

How would you do this? Like this

std::vector<std::string> stackTrace();

or provide functions that can be applied to the stack trace, e.g.

std::eek:stream& operator<<( std::eek:stream&, const StackTrace& );

Your implication here of a StackTrace class would be my choice. Along
with StackTraceItem class and whatever other classes embody the domain
entities. Then as you've shown each of these classes could be
streamable. The StackTrace class could then provide a container
interface including the expected typedefs, iterators and methods.

Jeff
 
D

DeMarcus

Jeff said:
Your implication here of a StackTrace class would be my choice. Along
with StackTraceItem class and whatever other classes embody the domain
entities. Then as you've shown each of these classes could be
streamable. The StackTrace class could then provide a container
interface including the expected typedefs, iterators and methods.

Jeff

I agree with you that one should not be afraid of making classes of even
the simplest things. But sometimes I just feel to be lazy, and in this
case the stack trace is just a list of text, so just to get up running
with a decent solution I chose to just provide a container.

Then came my mind block; I always return something like
std::vector<std::string>, but is that the best way to return a
container? How are containers returned with the new C++0x rvalue
reference for instance?
 
D

DeMarcus

Sousuke said:
Isn't that just a more complicated and unsafe way of doing:

v = aList;

?


I recently started a thread on that subject (whether "out" parameters
should be pointers instead of references):

http://groups.google.com/group/comp.lang.c++/browse_thread/thread/697f5fbff47a94e3#

It seems most agreed that it's a dumb guideline.

I don't think it's a /dumb/ guideline. I was thinking in those guideline
terms myself before. I thought that it would be easy to see whether a
variable would be altered if providing the address of it. E.g.

fnc( &myVar );

would give a hint of that myVar is going to be modified. However, if you
provide something that already is a pointer it would look like this.

fnc( myVar );

And therefore such guideline could be misleading.

That's the preffered way if the object being returned is a member of a
class (which means that the method is just a simple accessor
(getter)). More generally, it's ok as long as the object's lifetime is
well-defined and known to the caller (in the case of a member
variable, the lifetime is the same as that of its containing object).


Seems pointless.


Either "vector<A> getList()" or "void getList(vector<A>&)" if I need
copying, or "const vector<A>& getList() const" (and possibly a non-
const overload) if the returned object is a member variable.

Sometimes one doesn't need to copy but to return a newly created
container. E.g.

std::vector<std::string> getVector()
{
std::vector<std::string> hwVector;
hwVector.push_back( "Hello World" );
return hwVector;
}

I wonder how the new rvalue reference will be used with return values.
Like this?

std::vector<std::string>&& getVector()
{
std::vector<std::string> hwVector;
hwVector.push_back( "Hello World" );
return std::move( hwVector );
}

Do you know?
 
J

James Kanze

Here are a couple of ways to return some list of items.
struct A
{
};
std::vector<A> aList; // Some list of items.
// Returning a copy.
std::vector<A> getList() { return aList; }

That's generally the preferred way. Until the profiler says
otherwise.
void getList( std::vector<A>& v )
{
std::copy( aList.begin(), aList.end(), v.begin() );
}

That should be:

std::copy( aList.begin(), aList.end(), std::back_inserter(v) );
void getList( std::vector<A>* v )
{
std::copy( aList.begin(), aList.end(), v->begin() );
}

Same thing here. You should be using sd::back_inserter(*v),
rather than v->begin().

Whether you use a pointer or a reference in this case depends on
the local coding conventions.
// Returning a reference to aList.
const std::vector<A>& getList() { return aList; }

Where does aList live? The semantics here are distinctly
different from those of the previous versions, and the choice
between this version and one of the previous should be made
according to the desired semantics.
const std::vector<A>::const_iterator& getList()
{
return aList.begin();
}

This simply doesn't work. You're returning a reference to a
temporary.
Do you know more ways to return a list? What's your preferred
way to return a list of items?

The only way to "return" a list is to return it.
Also, here comes another trickier one. Let's say I have a map
instead and want to return the keys.
std::map<std::string, A> aMap;
// Returning a copy of the keys.
std::vector<std::string> getList()
{
std::vector<std::string> aKeys;
auto keysEnd = aMap.end();
for( auto i = aMap.begin(); i != keysEnd; ++i )
aKeys.push_back( (*i).first );
return aKeys;
}
void getList( std::vector<std::string>& v )
{
auto keysEnd = aMap.end();
for( auto i = aMap.begin(); i != keysEnd; ++i )
v.push_back( (*i).first );
}
void getList( std::vector<std::string>* v )
{
auto keysEnd = aMap.end();
for( auto i = aMap.begin(); i != keysEnd; ++i )
v->push_back( (*i).first );
}
// But is it even possible to return a reference to // the
keys in a map?

It's possible to return a reference to a single key, but it's
not possible to return a reference to some collection which
doesn't exist otherwise.
const std::vector<std::string>& getList() { /* What here? */ }
const std::vector<std::string>::const_iterator& getList()
{
/* What here? */
}
How do you usually deal with these kind of list returns?

I return what I should return, until the profiler says
otherwise. In which case, I use an out argument, whose format
(reference or pointer) depends on the local coding conventions.
 
J

James Kanze

DeMarcus wrote:
I often use output iterators. So, my function signature looks
as follows:
template < typename OutIter >
OutIter get_items ( OutIter where, other args );

Which means you're using a template. Which would be nice if
templates really worked, but as they are currently implemented
in most compilers, they require putting the implementation of
the function in the header. Which means that they can't really
be used unless the function is absolutely trivial and never
changes.
That way, the client can decide which data structure should be
used when the items are to be stored.

At a price of unacceptable coupling. This is an excellent
solution for ultra-stable basic library code (e.g. like the
standard library), but simply doesn't work at higher levels.
 
J

James Kanze

This one is OK, and will be efficient with modern compiler.

That depends on the context and the compiler. I've found that
in many contexts, if the vector is large, it's not efficient
with g++ or VC++ (or Sun CC). But if you can use better
compilers, maybe.

Anyway, this is clearly the preferred solution until the
profiler says otherwise.
This one's signature is OK as an opt-in alternative to the
first one (i.e. provide /both/, or just the first one).
However, the implementation is incorrect unless you assume
that the argument is of exactly the right size for the result
(and that assumption would be unrealistic, to put it mildly).
You could write it like
void getList( std::vector< A >& v )
{
std::vector< A >( aList.begin(), aList.end() ).swap( v );
}

Or simply use clear and a back_inserter. Or resize the target
first. The optimal solution will depend on context.
This one is just bad. Why would you want to support
nullpointer argument? If someone calls 'getList' it's in order
to get that list, not in order to do nothing.

The choice depends on the local coding conventions.
Anyway, under normal assumptions the implementation is incorrect.
This one's OK if you're clear on what it does.

It's OK if you actually have an aList somewhere, and you want to
return it.
This is one is just silly, the caller can't do anything
reasonable with the returned iterator.
How about ways to return lists, instead of vectors (arrays)?
That doesn't make sense without a lot more explanation of
exactly what you mean by "list" and in what context you'd want
to return -- what?

Yes and no. The "preferred" way of returning something
(anything, including a list of whatever) is to return it. You
only vary from that when the profiler says you must. In which
case, you have the context, and you adopt the solution most
suited to the context.
How about defining an iterator that walks through the keys.
Then you don't have to create all those string objects.

A transforming iterator. Boost has some good code which will
allow you to do this very simply. Of course, you'll need two
functions: listBegin and listEnd, rather than just one, but this
does allow the most freedom for the user.
 
J

James Kanze

On May 12, 3:18 am, DeMarcus <[email protected]> wrote:

[...]
Isn't that just a more complicated and unsafe way of doing:
v = aList;

The two don't have the same semantics. At all.
I recently started a thread on that subject (whether "out"
parameters should be pointers instead of references):

It seems most agreed that it's a dumb guideline.

I don't see where you got that. It's an arbitrary guideline, in
the sense that there is no right answer. Different companies
will use different guidelines---there are pros and cons for
each.

[...]
Either "vector<A> getList()" or "void getList(vector<A>&)" if I need
copying, or "const vector<A>& getList() const" (and possibly a non-
const overload) if the returned object is a member variable.

The only "clean" solution is "vector<A> getList()".
Regretfully, it can have significant overhead if the list
contains a lot of elements, and the function is called in a
tight loop. In which case, you choose among a number of other
solutions, depending on the context and the local coding
guidelines.
 
J

James Kanze

Sousuke wrote:

[...]
I don't think it's a /dumb/ guideline.

Certainly not. It's an arbitrary guideline, in the sense that
there are no killer arguments for any of the alternatives.
There are several reasonable choices (including this one).
I was thinking in those guideline terms myself before. I
thought that it would be easy to see whether a variable would
be altered if providing the address of it.

I sort of prefer it too. But not to the point of saying that
the other choices are dumb. The only "dumb" decision here is
not recognizing that several options are equally valid, and that
your choice is more or less arbitrary.
fnc( &myVar );
would give a hint of that myVar is going to be modified.
However, if you provide something that already is a pointer it
would look like this.
fnc( myVar );
And therefore such guideline could be misleading.

Yes and no. Presumably, you know what you're passing.
(Presumably, aussi, the function name would indicate what it
does, so you'd know what it modifies. Except, of course, that
in some numerics work, and probably in other domains as well,
you might have two or three out parameters.)
 
I

Ian Collins

Which means you're using a template. Which would be nice if
templates really worked, but as they are currently implemented
in most compilers, they require putting the implementation of
the function in the header. Which means that they can't really
be used unless the function is absolutely trivial and never
changes.

Oh come on James, that's going a bit too far. What really matters in
practice is how long you have to wait for a build. If that becomes too
big a deal, throw more hardware at it.
 
K

Kai-Uwe Bux

Ian said:
Oh come on James, that's going a bit too far. What really matters in
practice is how long you have to wait for a build. If that becomes too
big a deal, throw more hardware at it.

Well, I understand that there are shops where templates are prohibited by
local coding guidelines. I would suppose they have those rules in place for
good reasons. Admittedly, under those circumstances, using the OutIter
signature is not feasible.

I would, however, maintain that templates _should_ be fine for many
projects. I do see that they interact poorly with the C++ model of separate
compilation and source code file inclusion: taken together, the package does
not really scale all that well. I am just not certain at which point scaling
becomes a valid reason to ban templates.


Best

Kai-Uwe Bux
 
J

Jorgen Grahn

Alf P. Steinbach wrote: ....

That's nice! Where do I find tricks like that? I don't find such things
in Josuttis' book.

It's "just" a fancy way of saying:

std::vector< A > tmp( aList.begin(), aList.end() );
tmp.swap( v );

I hope every half-decent book stresses the importance of swapping, and
clearly shows how all the standard containers can be constructed from
any kind of suitable iterator.

/Jorgen
 
A

Alf P. Steinbach

That depends on the context and the compiler. I've found that
in many contexts, if the vector is large, it's not efficient
with g++ or VC++ (or Sun CC).

Huh, that's news to me.

I'm pretty skeptical about that claim since both g++ and MSVC do RVO
optimization by default, but I'll try to remember to check this.

If you're talking about comparing it with a situation where you can avoid
reallocation of the vector's buffer then that doesn't depend on the compiler.

But if you can use better
compilers, maybe.

Anyway, this is clearly the preferred solution until the
profiler says otherwise.

Yah, agreed.

Or simply use clear and a back_inserter. Or resize the target
first. The optimal solution will depend on context.

I like this way as a "default" for this function signature because it guarantees
to get rid of the old buffer allocation (so that one does not hang on to the
largest buffer size forever), and because it's simplest.

The choice depends on the local coding conventions.

Yes, but one simply shouldn't work for Google as a C++ programmer. :)

It's OK if you actually have an aList somewhere, and you want to
return it.

I think you mean, if the lifetime of 'aList' is sufficient. In the OP's example
it is.

Yes and no. The "preferred" way of returning something
(anything, including a list of whatever) is to return it. You
only vary from that when the profiler says you must. In which
case, you have the context, and you adopt the solution most
suited to the context.

This seems to conflate two different meanings of "return". For example, if you
have a pointer p you might return *p, what's "it" that's being returned? So as I
wrote, in order to answer the OP's question it would need to more details.

A transforming iterator. Boost has some good code which will
allow you to do this very simply. Of course, you'll need two
functions: listBegin and listEnd, rather than just one, but this
does allow the most freedom for the user.

I didn't know about the Boost adaptors, I'll look into it (later); thanks!


Cheers,

- Alf
 
J

Jeff Flinn

DeMarcus said:
I agree with you that one should not be afraid of making classes of even
the simplest things. But sometimes I just feel to be lazy, and in this
case the stack trace is just a list of text, so just to get up running
with a decent solution I chose to just provide a container.

Aah, but if you do anything with that text other than simply write it
out verbatim, you've got behavior leaking all over your application when
you process the item. By decomposing at this point I always end up with
some abastractions that I can reuse in multiple places.

I would even start looking at where the data for this vector is coming
from, which is probably some stream, then I'd develop the grammar to
parse that data directly into domain entities. This always ends up using
less memory, fewer cycles and is more flexible with less coupling.
Then came my mind block; I always return something like
std::vector<std::string>, but is that the best way to return a
container? How are containers returned with the new C++0x rvalue
reference for instance?

IIRC, rvalue refs doesn't change what or how you return an unnamed
object from a function, but does provide a way for consumers to avoid
copies by providing a means to overload on another type and in the case
of vector to only swap it's internal data pointer rather than copy all
items.

Jeff
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,905
Latest member
Kristy_Poole

Latest Threads

Top