From: Gerry Hickman on
Hi Doug,

Would it be possible for you to post a more detailed example of your
code? I understand my pointer version, and the "Charles Wang"
'references' version, but I didn't quite understand your version.

Regarding the count of instances, I'm not against it, but in theory I
can grab this after the function returns, however, there is an issue of
"reserving" (as you pointed out) if the number of classes was large.

Either way, I think all the code we've been discussing will be more
elegant than the official DevCon Device Classes enum sample code!

I'm actually designing a low-level version of the CIM_MediaAccessDevice
WMI class. This will get all block level devices such as CD-ROM, Data
Stick, Floppy, PhysicalDisk etc.

Doug Harrison [MVP] wrote:
> On Fri, 10 Aug 2007 22:47:34 +0200, "Bo Persson" <bop(a)gmb.dk> wrote:
>
>> Doug Harrison [MVP] wrote:
>> :: On Fri, 10 Aug 2007 08:59:05 +0200, Ulrich Eckhardt
>> :: <eckhardt(a)satorlaser.com> wrote:
>> ::
>> ::: Gerry Hickman wrote:
>> :::: Doug Harrison offered this example:
>> ::::
>> :::: ----- example start -----
>> ::::
>> :::: I would use pass-by-reference to avoid this needless cost, e.g.
>> ::::
>> :::: vector<string>::size_type
>> :::: void GetDeviceClasses(vector<string>& guids)
>> :::: {
>> ::: [...]
>> :::: returns guids.size();
>> :::: }
>> :::
>> ::: Funny. Talking about needless costs and then returning redundant
>> ::: data - the size can be retrieved from the vector.
>> ::
>> :: What's "funny" is to compare returning a vector<string> by value to
>> :: returning its size, the latter being as close to a free operation
>> :: as there is, both in terms of complexity and exception safety. Not
>> :: to mention, returning the size is a useful thing to do.
>>
>> How do you know that it is useful? Always?
>
> Often, after using a function with a name such as "GetDeviceClasses", a
> programmer wants to know how many such classes were found; he may be
> interested in the exact number, or he may just treat it as a boolean.
> Provided one can indicate errors in some other way, there's no reason not
> to return the number of items that were found, elements read, etc.
>
>> Assuming that we are trying to optimize a time-critical piece of code,
>> why return a value that isn't asked for? Especially as it is also
>> returned as a part of the guids parameter.
>
> The code in question populates a vector<string>, and judging by its name,
> probably enumerates the registry. I don't understand how anyone could worry
> about the efficiency of returning vector::size() in this context.
>
> (Granted, if you were talking about std::list, you might have a very, very
> tiny point, but to date, I'm unaware of anyone making vector::size worse
> than O(1).)
>
>> It is also often not considered good style to have both a return value
>> and out-parameters.
>
> This is not an example of bad style.
>
> (Q: What do you think this interface is equivalent to, if anything? To help
> you focus, you can limit yourself to standard functions.)
>
>> If you need to, you can have several
>> out-parameters, and not single out one of them as a return value.
>
> Yes, you can do that if you need to.
>


--
Gerry Hickman (London UK)
From: Ulrich Eckhardt on
Doug Harrison [MVP] wrote:
> On Fri, 10 Aug 2007 08:59:05 +0200, Ulrich Eckhardt
> <eckhardt(a)satorlaser.com> wrote:
>>Gerry Hickman wrote:
>>> Doug Harrison offered this example:
>>>
>>> ----- example start -----
>>>
>>> I would use pass-by-reference to avoid this needless cost, e.g.
>>>
>>> vector<string>::size_type
>>> void GetDeviceClasses(vector<string>& guids)
>>> {
>>[...]
>>> returns guids.size();
>>> }
>>
>>Funny. Talking about needless costs and then returning redundant data -
>>the size can be retrieved from the vector.
>
> What's "funny" is to compare returning a vector<string> by value to
> returning its size, the latter being as close to a free operation as there
> is, both in terms of complexity and exception safety.
> Not to mention, returning the size is a useful thing to do.

Nah, it increases the complexity for the reader. My question would be how
the returnvalue differs from the size. Is it perhaps only the number of
elements added to the vector? No, seriously, I'd prefer a straight-forward
interface _without_ redundancy.

>>Anyway, why would you write anything but clear code unless you first
>>determined that it's a bottleneck? Just return the vector by value.
>
> I don't know what's "funnier"; suggesting the code I presented isn't
> "clear", recommending returning a vector<string> by value, or equating
> returning a vector<string> by value with returning size().

The clearest thing is IMHO returning the result of a function by
using 'return'.

Now, concerning efficiency:
a)
vector const& v = my_function();
b)
vector v;
your_function(v);

Which of those is more efficient? You claim that it's b), but using a modern
compiler they can be equivalent and a) is much clearer because you see
immediately that there is something returned. You might even be able to
drop the reference and it would remain the same code.

I think it's about where you draw the line. If it was not a vector of
strings but a string, would you return it by value? I would. If it
contained the content of a whole file? I wouldn't. How about vector<char>
or vector<int>? Or vector<some_POD>? I can't tell you where one of these or
the original example degrades in performance so far that you can't afford
passing it by value anymore, but until I know that I stay with the clearest
possible code.

> You could almost take it on the road, I think. :)

I'm not familiar with that term...

Uli

From: Gerry Hickman on
Hi Ulrich,

>> but when I came to actually code this, I ran into some problems.
>
> This doesn't help. What problems?

I was confused by Doug's example, I'd copied it literally

vector<string>::size_type
void GetDeviceClasses(vector<string>& guids)
{
guids.clear();
// If you can estimate n, reserve can eliminate reallocations.
// guids.reserve(n);
...
returns guids.size();
}

I guessed 'returns' should be a comment, but the first two lines didn't
make sense with void following vector<string>::size_type, I guess I was
supposed to _replace_ void with vector<string>::size_type, seems obvious
now.

>> void PopulateStrings(vector<string> * guids)
>> {
>> guids->clear();
>> guids->push_back("test1");
>> guids->push_back("test2");
>> }
>
> While this code will work, there is one thing I object to: in C++, where you
> have references, a pointer[1] means to me that something is optional, i.e.
> passing zero is okay, but you don't mean that. Still, you must handle that
> case, so either you just return (making it a non-error), throw an exception
> (making it a runtime error) or use assert() (making it a programmer's
> error).

Does this only apply to the 'pointer' version, or does it apply to the
'references' version too?

--
Gerry Hickman (London UK)
From: Gerry Hickman on
Thanks Charles,

I tested your code, it works great, and is also very easy to read.

Charles Wang[MSFT] wrote:
> Hi Gerry,
> Could you please let us know what the problems you ran into if you used
> Doug's suggestion?
>
> It should also work if you use reference as following:
> ===================================
> vector<string> guids;
> PopulateStrings(guids);
> cout << "Count of guids is now " << guids.size(); // prints 2
>
> void PopulateStrings(vector<string> & guids)
> {
> guids.clear();
> guids.push_back("test1");
> guids.push_back("test2");
> }
> ==================================
>
> Best regards,
> Charles Wang
> Microsoft Online Community Support
> =====================================================
> When responding to posts, please "Reply to Group" via
> your newsreader so that others may learn and benefit
> from this issue.
> ======================================================
> This posting is provided "AS IS" with no warranties, and confers no rights.
> ======================================================
>
>
>


--
Gerry Hickman (London UK)
From: Gerry Hickman on
Gerry Hickman wrote:

> Would it be possible for you to post a more detailed example

Sorry, I understand it now.

--
Gerry Hickman (London UK)