STL Container class that holds no more than one object?

J

jl_post

Hi,

I was wondering if there was such a thing as an STL container class
that could only hold 0 or 1 instances of an object -- sort of like a
std::vector than can only hold a maximum of one object.

This class would come in handy if I want to create a function/
method that may or may not return a valid value. As a trivial
example, I could create a function that divides two numbers, but only
returns a valid value if the input allows for it:

std::???<double> value = divide(12, 2); // returns a value of 6
std::???<double> value = divide(12, 0); // returns an empty value

This behavior would be similar to Perl's often-used convention of
returning "undef" if a value could not be retrieved or computed.

The reason I want a class like this is because I have seen several
times in C++ code where a value needs to be known if it's set or not.
Often, 0 or -1 is often used as a "not set" indicator, but that
doesn't always work for all values (like temperature values, or
latitude & longitude, which can easily be negative).

Often the workaround used for this is to return a pointer, and if
the pointer is NULL then the value can be assumed to be unset, and if
the pointer is non-NULL then it can be de-referenced to get the real
value, like this:

double *ptr = divide(a, b);
if (ptr)
std::cout << "a/b = " << *ptr << std::endl;
else
std::cout << "No answer computed." << std::endl;
delete ptr;

However, I don't particularly like this approach, as it requires the
programmer to manage the memory (and necessarily know whether the
pointer should be free()d or delete()d).

I suppose I can always write my own container class (that shouldn't
be too hard), or just return a std::vector with zero or one elements
(but then I'd have to clearly document that the return vector will
never have a plural number of elements), but that almost feels
overkill to me, like trying to use a hammer to swat a fly.

So I thought I'd ask if such an STL class existed, so in case it
did it would save me the trouble of using a work-around. But if it
doesn't exist, what work-around would you suggest I use?

Thanks!

-- Jean-Luc
 
S

Sana

Hi,

   I was wondering if there was such a thing as an STL container class
that could only hold 0 or 1 instances of an object -- sort of like a
std::vector than can only hold a maximum of one object.

   This class would come in handy if I want to create a function/
method that may or may not return a valid value.  As a trivial
example, I could create a function that divides two numbers, but only
returns a valid value if the input allows for it:

   std::???<double> value = divide(12, 2);  // returns a value of 6
   std::???<double> value = divide(12, 0);  // returns an empty value

   This behavior would be similar to Perl's often-used convention of
returning "undef" if a value could not be retrieved or computed.

   The reason I want a class like this is because I have seen several
times in C++ code where a value needs to be known if it's set or not.
Often, 0 or -1 is often used as a "not set" indicator, but that
doesn't always work for all values (like temperature values, or
latitude & longitude, which can easily be negative).

   Often the workaround used for this is to return a pointer, and if
the pointer is NULL then the value can be assumed to be unset, and if
the pointer is non-NULL then it can be de-referenced to get the real
value, like this:

   double *ptr = divide(a, b);
   if (ptr)
      std::cout << "a/b = " << *ptr << std::endl;
   else
      std::cout << "No answer computed." << std::endl;
   delete ptr;

However, I don't particularly like this approach, as it requires the
programmer to manage the memory (and necessarily know whether the
pointer should be free()d or delete()d).

   I suppose I can always write my own container class (that shouldn't
be too hard), or just return a std::vector with zero or one elements
(but then I'd have to clearly document that the return vector will
never have a plural number of elements), but that almost feels
overkill to me, like trying to use a hammer to swat a fly.

   So I thought I'd ask if such an STL class existed, so in case it
did it would save me the trouble of using a work-around.  But if it
doesn't exist, what work-around would you suggest I use?

use std::pair

// untested code

#include <pair>
#include <iostream>

std::pair<int, double> divide(double numerator, double denominator)
{
if (denominator == 0.0)
return std::pair(1, 0.0);

return std::pair(0, numerator/denominator);
}

int main()
{
std::pair<int, double> result = divide(3.0, 2.0);
if (result.first == 0)
std::cout << result.second;
else
std::cout << "division by zero";

}
 
P

peter koch

Hi,

   I was wondering if there was such a thing as an STL container class
that could only hold 0 or 1 instances of an object -- sort of like a
std::vector than can only hold a maximum of one object.

   This class would come in handy if I want to create a function/
method that may or may not return a valid value.  As a trivial
example, I could create a function that divides two numbers, but only
returns a valid value if the input allows for it:

   std::???<double> value = divide(12, 2);  // returns a value of 6
   std::???<double> value = divide(12, 0);  // returns an empty value

   This behavior would be similar to Perl's often-used convention of
returning "undef" if a value could not be retrieved or computed.

   The reason I want a class like this is because I have seen several
times in C++ code where a value needs to be known if it's set or not.
Often, 0 or -1 is often used as a "not set" indicator, but that
doesn't always work for all values (like temperature values, or
latitude & longitude, which can easily be negative).

   Often the workaround used for this is to return a pointer, and if
the pointer is NULL then the value can be assumed to be unset, and if
the pointer is non-NULL then it can be de-referenced to get the real
value, like this:

   double *ptr = divide(a, b);
   if (ptr)
      std::cout << "a/b = " << *ptr << std::endl;
   else
      std::cout << "No answer computed." << std::endl;
   delete ptr;

However, I don't particularly like this approach, as it requires the
programmer to manage the memory (and necessarily know whether the
pointer should be free()d or delete()d).

   I suppose I can always write my own container class (that shouldn't
be too hard), or just return a std::vector with zero or one elements
(but then I'd have to clearly document that the return vector will
never have a plural number of elements), but that almost feels
overkill to me, like trying to use a hammer to swat a fly.

   So I thought I'd ask if such an STL class existed, so in case it
did it would save me the trouble of using a work-around.  But if it
doesn't exist, what work-around would you suggest I use?

If you don't want to throw an exception (which might be ludicrous or
obvious depending on your real problem), I'd suggest using
boost::eek:ptional which was designed specifically for situations like
this. Sanas suggestion of using std::pair is not bad, but I certainly
would prefer the Boost solution any day.

/Peter
 
J

James Kanze

I was wondering if there was such a thing as an STL container
class that could only hold 0 or 1 instances of an object --
sort of like a std::vector than can only hold a maximum of one
object.

Not a container, since it wouldn't make much sense: a container
supports iterators, etc., and you don't need iterators for 0 or
1.
This class would come in handy if I want to create a function/
method that may or may not return a valid value.

The classical solution for that is a Fallible class, see Barton
and Nackman.

[...]
Often the workaround used for this is to return a pointer, and
if the pointer is NULL then the value can be assumed to be
unset, and if the pointer is non-NULL then it can be
de-referenced to get the real value, like this:

double *ptr = divide(a, b);
if (ptr)
std::cout << "a/b = " << *ptr << std::endl;
else
std::cout << "No answer computed." << std::endl;
delete ptr;
However, I don't particularly like this approach, as it
requires the programmer to manage the memory (and necessarily
know whether the pointer should be free()d or delete()d).

It's a good approach if the return value is supposed to be a
table entry or something similar, e.g. a find function; the
pointer points to an existing object in the table. It's a
possible approach for factory methods which may fail; client
code expects to delete anything returned from a factory method
(and in fact, they often return std::auto_ptr). I wouldn't use
it otherwise.
I suppose I can always write my own container class (that
shouldn't be too hard), or just return a std::vector with zero
or one elements (but then I'd have to clearly document that
the return vector will never have a plural number of
elements), but that almost feels overkill to me, like trying
to use a hammer to swat a fly.
So I thought I'd ask if such an STL class existed, so in case
it did it would save me the trouble of using a work-around.
But if it doesn't exist, what work-around would you suggest I
use?

There's an implementation of Fallible at my site, but it's a
simple enough template class that you should be able to write
one yourself in little time. The version at my site
(http://kanze.james.neuf.fr/code-en.html, in the Basic
subsystem) has been extended to support extended error codes,
and I have a more recent version which supports objects without
default constructors, but most of the time, you don't need all
that. (I'd been using it for 7 or 8 years before I added the
extended error codes, and I only added support for objects
without default constructors very recently.)
 
N

Noah Roberts

However, I don't particularly like this approach, as it requires the
programmer to manage the memory (and necessarily know whether the
pointer should be free()d or delete()d).

Not if you use a smart pointer.
 
T

Thomas Beckmann

Hi,
double *ptr = divide(a, b);
if (ptr)
std::cout << "a/b = " << *ptr << std::endl;
else
std::cout << "No answer computed." << std::endl;
delete ptr;

a simple solution would be to returns a bool as error code and put the
result in an output variable passed by reference:

bool divide(double& out, double a, double b);

Then clients just do:

double result;
if(divide(result, a, b))
std::cout << "a/b = " << result << std::endl;
else
std::cout << "No answer computed." << std::endl;

Cheap and easy...


Regards,
Thomas.
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top