Is there any way to return either NULL or a SYSTEMTIME object? will
it work in C++?

as in Java, one can return either NULL or an object, does C++ has
something similar?

Is the following code OK for C++?
=================

SYSTEMTIME Table::Get(char* FieldName)
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();

if (vtValue.vt == VT_NULL) {
return NULL;
}
SYSTEMTIME m_st;
VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &m_st);
return m_st;
}

Re: return value by Doug

Doug
Wed Apr 16 20:21:22 CDT 2008

On Wed, 16 Apr 2008 17:43:45 -0700, Carmen Sei <fatwallet951@yahoo.com>
wrote:

>Is there any way to return either NULL or a SYSTEMTIME object? will
>it work in C++?
>
>as in Java, one can return either NULL or an object, does C++ has
>something similar?

In Java, you're returning a reference to an object or NULL. The
corresponding thing in C++ would be to return a pointer or NULL.

>Is the following code OK for C++?
>=================
>
>SYSTEMTIME Table::Get(char* FieldName)
>{
> _variant_t vtValue;
> vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();
>
> if (vtValue.vt == VT_NULL) {
> return NULL;
> }
> SYSTEMTIME m_st;

The "m_" prefix signifies "member variable" and shouldn't be used to name
local variables.

> VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &m_st);
> return m_st;
>}

No, SYSTEMTIME is a struct, not a pointer, and to return a SYSTEMTIME is to
return the entire struct by value. As C++ is not garbage-collected, you
really can't return a pointer here. (You could make m_st static and return
a pointer, but then you're no longer thread-safe, and each call to Get
destroys the previous result. You could instead create it dynamically, but
then the caller would have to assume ownership and delete the object.
Neither are recommended.) What you can do is change the function as
follows:

bool Table::Get(char* FieldName, SYSTEMTIME& st)
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();

if (vtValue.vt == VT_NULL) {
return false;
}
VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &st);
return true;
}

--
Doug Harrison
Visual C++ MVP

Re: return value by Carmen

Carmen
Thu Apr 17 00:03:03 CDT 2008

Then C++ programmer most of time will pass in a reference (SYSTEMTIME&
st) most of time for passing value back to caller function?

bool Table::Get(char* FieldName, SYSTEMTIME& st)
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();

if (vtValue.vt == VT_NULL) {
return false;
}
VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &st);
return true;
}

=====================
another way to do this is -
SYSTEMTIME* Table::Get(char* FieldName)

=====================
but the following is better way for returning value back to caller
function and most programmer do this way??
bool Table::Get(char* FieldName, SYSTEMTIME& st)


>No, SYSTEMTIME is a struct, not a pointer, and to return a SYSTEMTIME is to
>return the entire struct by value. As C++ is not garbage-collected, you
>really can't return a pointer here.

Re: return value by dertopper

dertopper
Thu Apr 17 03:01:06 CDT 2008

Carmen Sei wrote:
> Is there any way to return either NULL or a SYSTEMTIME object? =A0will
> it work in C++?
>
> as in Java, one can return either NULL or an object, does C++ has
> something similar?
>
> Is the following code OK for C++?
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> SYSTEMTIME Table::Get(char* FieldName)
> {
> =A0 =A0 =A0 =A0 _variant_t =A0vtValue;
> =A0 =A0 =A0 =A0 vtValue =3D m_Rec->Fields->GetItem(FieldName)->GetValue();=

>
> =A0 =A0 =A0 =A0 if (vtValue.vt =3D=3D VT_NULL) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return NULL;
> =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 SYSTEMTIME m_st;
> =A0 =A0 =A0 =A0 VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &m_=
st);
> =A0 =A0 =A0 =A0 return m_st;
> }

Have you tried to compile it?

C++ distinguishes between objects and pointers to objects (in contrast
to Java, where everything is a pointer to an object). Thus you can
specify in C++ that a function will always return a valid object
(something that cannot be NULL, so you don't have to write code to
check that the return value is actually non-NULL) by making the return
type an object:
SYSTEMTIME Table::Get(char* FieldName)
This will always return a valid SYSTEMTIME (unless it throws an
exception).
The semantics you want to express is a bit different. What you
actually want to specify is a method that returns a valid SYSTEMTIME
when a certain condition is met, or a value that indicates that no
meaningful SYSTEMTIME could be returned because the condition is _not_
met (in your case the condition is that the data base contains an
entry that can be coerced into a SYSTEMTIME in the specified field).

You have two alternatives to design this:
(A) Use a special DATETIME value that indicates that you could not
retrieve such a value from the data base (for example you could use
the time where all members are set to zero).
(B) Return a pointer to a DATETIME, which will be NULL if the
condition isn't met. In this case the called method will have to
allocate memory on the heap, so the calling entity would have to
ensure that this memory is properly released. The standard way of
doing this is making the return type an auto_ptr:
std::autoptr<SYSTEMTIME> Table::Get(char* FieldName);
The auto_ptr will ensure that the memory is properly released, and
above all this is the exception-safe way of returning new'ed objects
(see Herb Sutter's "Exceptional C++" for a better description).

Both alternatives are equally well suited to do what you want,
alternative B is a bit closer to the way a Java programmer would
handle such a case.

Regards,
Stuart

Re: return value by Ulrich

Ulrich
Thu Apr 17 02:54:03 CDT 2008

Note up front: this has nothing to do with the MFC, dropping mpvm from the
list of groups.

Carmen Sei wrote:
> Is there any way to return either NULL or a SYSTEMTIME object? will
> it work in C++?
>
> as in Java, one can return either NULL or an object, does C++ has
> something similar?

Doug already pointed out the differences to the Java object model, and that
the closest in C++ is a pointer.

> Is the following code OK for C++?
> =================
>
> SYSTEMTIME Table::Get(char* FieldName)
> {
> _variant_t vtValue;
> vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();
>
> if (vtValue.vt == VT_NULL) {
> return NULL;
> }
> SYSTEMTIME m_st;
> VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &m_st);
> return m_st;
> }

No:
1. In what way is 'FieldName' modified? If it isn't, make it 'const',
because otherwise the function implies that it is. Other than that, in C++
you should use a string class like std::string or CString.
2. Use initialisation instead of assignment, i.e. merge the two first line
of this function. Further, it helps actually making such values constant,
so you don't accidentally modify them later on.
3. I'm pretty sure that it doesn't compile, so it obviously isn't
correct. ;)


Doug mentioned some ways to solve this, but I'd like to add two of them:

1. If you can't return something from a function, just like in Java, you can
throw an exception. I would for example use std::runtime_error from
<stdexcept> which allows carrying a std::string as additional info. In some
cases it would even make sense to derive an own exception type. This avoids
having to check each and every returnvalue when the only thing you can do
is to forward the error.
2. If you need to pass an object to the caller, and the caller is supposed
to assume ownership of it, use std::auto_ptr. Its semantics are a bit
confusing at first, but they come very handy in practice.

Uli

--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Michael Wöhrmann, Amtsgericht Hamburg HR B62 932

Re: return value by Ulrich

Ulrich
Thu Apr 17 03:09:38 CDT 2008

Ulrich Eckhardt wrote:
> Doug mentioned some ways to solve this, but I'd like to add two of them:
[...]
3. Use 'boost::optional<>' in order to signal that the function can return
nothing, too.

Uli

--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Michael Wöhrmann, Amtsgericht Hamburg HR B62 932

Re: return value by Ben

Ben
Thu Apr 17 09:58:00 CDT 2008

Carmen Sei wrote:
> Then C++ programmer most of time will pass in a reference (SYSTEMTIME&
> st) most of time for passing value back to caller function?
>
> bool Table::Get(char* FieldName, SYSTEMTIME& st)
> {
> _variant_t vtValue;
> vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();
>
> if (vtValue.vt == VT_NULL) {
> return false;
> }
> VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &st);
> return true;
> }
>
> =====================
> another way to do this is -
> SYSTEMTIME* Table::Get(char* FieldName)
>
> =====================
> but the following is better way for returning value back to caller
> function and most programmer do this way??
> bool Table::Get(char* FieldName, SYSTEMTIME& st)

The reason pass-by-reference is better than return is that the caller both
allocates and frees the memory, so any allocator can be used. When
returning a pointer, the callee allocates but the caller frees, and this is
an opportunity for trouble if the caller doesn't free using the right
allocator.