Re: Returning Nulls in Templates

Discussion in 'C++' started by Paul, Mar 20, 2011.

  1. Paul

    Paul Guest

    "Ruben Safir" <> wrote in message
    news:im43rn$4v8$...

    <Big snip>
    > ========================================================================================================================
    >
    > The problem is when I try to return NULLS or Zeros from accessory methods,
    > especially with
    > the operator[] overload in templates of the type message. These are
    > needed because the end
    > of the linked list is marked with zero values. First I was returning 0's.
    >
    > The reference returns in operator[] didn't like that saying they were
    > Temporary objects when
    > returned by NODE.value(). So I added a NODE.value_ref(). But when the
    > template class type
    > is std::string and i try to return 0, it says that class string is not
    > able to determine which operator= to use
    >
    > I tried to add an unk err member, but I can't initializing it according to
    > C++ iso standard, and it is still ambigious to
    > to string class when I try to assign it.
    >
    > I'm just frustrated to no end at this point and need advise as to how to
    > code this rationally.
    >


    Hey
    The problem is your list is not string friendly with statements like:
    unk err = 0;
    If unk is a std::string you get undefined behaviour if you assign a numeric
    to it.
    You'd be safer to use '\0' to null-initialise an unkown type.

    I think you should trim down your code a bit for debugging , there is alot
    of unneccessarry stuff there.

    HTH
     
    Paul, Mar 20, 2011
    #1
    1. Advertising

  2. Paul

    Paul Guest

    "Ruben Safir" <> wrote in message
    news:im5744$4v8$...
    > On Sun, 20 Mar 2011 12:03:16 +0000, Paul wrote:
    >
    >> You'd be safer to use '\0' to null-initialise an unkown type.

    >
    >
    >
    > That can be used for an number type, and pointer as well? That might be
    > just what I'm looking for.
    >
    > Ruben
    >


    It's good for pointers AFAIK, I'm not sure about all the exact rules for
    this being converted to floats and stuff, but its an easy fix for most
    implementations. I'd check it with some simple code to see if at least it
    works for all expected types on your implementation:

    int main(){

    float f = '\0';
    std::cout<< f;

    myType UDT = '\0';
    etc etc , for all expected types.
    }

    Or you could start scanning through the C++ standard. :)

    Your other alternative is to create some customs traits but then your
    talking about a completely different class design.

    HTH.
     
    Paul, Mar 20, 2011
    #2
    1. Advertising

  3. Paul

    James Kanze Guest

    On Mar 20, 3:39 pm, Ruben Safir <> wrote:
    > On Sun, 20 Mar 2011 12:03:16 +0000, Paul wrote:
    > > You'd be safer to use '\0' to null-initialise an unkown type.


    > That can be used for an number type, and pointer as well? That might be
    > just what I'm looking for.


    The correct way to initialize an unknown type is to use T().
    That works for numbers, pointers and smart pointers. Beyond
    that, as far as the compiler is concerned, 0, NULL, '\0' and
    false are all integral constants evaluating to 0. In code, I've
    seen two different conventions: use 0 systematically, for
    everything (except usually false), and use 0 for numeric values,
    NULL for pointers, '\0' for the nul character, and false for
    boolean values---in other words, behave as if the language were
    logically typed.

    --
    James Kanze
     
    James Kanze, Mar 20, 2011
    #3
  4. Paul

    Paul Guest

    "James Kanze" <> wrote in message
    news:...
    > On Mar 20, 3:39 pm, Ruben Safir <> wrote:
    >> On Sun, 20 Mar 2011 12:03:16 +0000, Paul wrote:
    >> > You'd be safer to use '\0' to null-initialise an unkown type.

    >
    >> That can be used for an number type, and pointer as well? That might be
    >> just what I'm looking for.

    >
    > The correct way to initialize an unknown type is to use T().


    Why didn't I think of that ..simply invoke the well known function T().
    *joking ofc* :)
     
    Paul, Mar 20, 2011
    #4
  5. Paul

    Paul Guest

    "Ruben Safir" <> wrote in message
    news:im7rfi$4v8$...
    > On Sun, 20 Mar 2011 11:37:37 -0700, James Kanze wrote:
    >
    >> On Mar 20, 3:39 pm, Ruben Safir <> wrote:
    >>> On Sun, 20 Mar 2011 12:03:16 +0000, Paul wrote:
    >>> > You'd be safer to use '\0' to null-initialise an unkown type.

    >>
    >>> That can be used for an number type, and pointer as well? That might
    >>> be just what I'm looking for.

    >>
    >> The correct way to initialize an unknown type is to use T(). That works
    >> for numbers, pointers and smart pointers. Beyond that, as far as the
    >> compiler is concerned, 0, NULL, '\0' and false are all integral
    >> constants evaluating to 0. In code, I've seen two different
    >> conventions: use 0 systematically, for everything (except usually
    >> false), and use 0 for numeric values, NULL for pointers, '\0' for the
    >> nul character, and false for boolean values---in other words, behave as
    >> if the language were logically typed.

    >
    >
    >
    > But it doesn't work with a string object, but strangely enough, Victor's
    > suggestion, which I had though about myself and rejected with out testing
    > because of the same facts that you stated here, works perfectly for all
    > the toyes I've tested now. It seems that '\0' is more universal and '0'
    >

    Be carefull '\0' is not the same as '0'.
    On ASCII platforms :
    '\0' == 0; //true null
    '0' == 0x30; //the character '0'


    HTH.
     
    Paul, Mar 21, 2011
    #5
  6. Paul

    James Kanze Guest

    On Mar 21, 3:39 pm, Ruben Safir <> wrote:
    > On Sun, 20 Mar 2011 11:37:37 -0700, James Kanze wrote:
    > > On Mar 20, 3:39 pm, Ruben Safir <> wrote:
    > >> On Sun, 20 Mar 2011 12:03:16 +0000, Paul wrote:
    > >> > You'd be safer to use '\0' to null-initialise an unkown type.


    > >> That can be used for an number type, and pointer as well? That might
    > >> be just what I'm looking for.


    > > The correct way to initialize an unknown type is to use T(). That works
    > > for numbers, pointers and smart pointers. Beyond that, as far as the
    > > compiler is concerned, 0, NULL, '\0' and false are all integral
    > > constants evaluating to 0. In code, I've seen two different
    > > conventions: use 0 systematically, for everything (except usually
    > > false), and use 0 for numeric values, NULL for pointers, '\0' for the
    > > nul character, and false for boolean values---in other words, behave as
    > > if the language were logically typed.


    > But it doesn't work with a string object,


    What doesn't work with a string object. A string object doesn't
    have a "nul" value, whatever that would mean. Regretfully,
    string(0) (or string(NULL)) is a syntactically legal expression,
    which results in undefined behavior.

    > but strangely enough, Victor's
    > suggestion, which I had though about myself and rejected with out testing
    > because of the same facts that you stated here, works perfectly for all
    > the toyes I've tested now. It seems that '\0' is more universal and '0'


    No. '\0' and 0 have the same value. The first has type char,
    the second type int. Both are null pointer constants (since
    both are integral constant expressions evaluating to zero).
    However, I would consider code using the first as a null point
    defective, since it corresponds to no established convention.
    As I said before, if you want a null pointer, use 0 or NULL
    (depending on the local conventions). If you want a default
    initialized value (e.g. in a template), use T(). If you want a
    nullable value (of an arbitrary type), use Nullable<T> (or
    Maybe<T>, or Fallible<T>, or boost::eek:ptional<T>). And if you
    don't know what you want, figure that out first.

    --
    James Kanze
     
    James Kanze, Mar 22, 2011
    #6
  7. Paul

    Paul Guest

    "Ruben Safir" <> wrote in message
    news:im91mr$4v8$...
    > On Mon, 21 Mar 2011 17:44:08 -0700, James Kanze wrote:
    >
    >> What doesn't work with a string object.

    >
    >
    >
    > string mystring = 0; returns a compiler error, "Ambiguous operator= of
    > some sort". Now a char * mystring = 0; doesn't have this problem,
    > although casting it is likely more appropriate.
    >
    > But when I'm creating a template, I'm not sure what my type might be and
    > I really want to return null and stop the function when I want to. It
    > chokes on returning Null for string types member function.
    >

    You can check to see if your type is a string.

    #include<type_traits>
    std::is_same<unk, std::string>::value

    This value will be true if both template arguments are the same type , and
    false otherwise.
     
    Paul, Mar 22, 2011
    #7
  8. Paul

    Paul Guest

    "James Kanze" <> wrote in message
    news:...
    > On Mar 21, 3:39 pm, Ruben Safir <> wrote:
    >> On Sun, 20 Mar 2011 11:37:37 -0700, James Kanze wrote:
    >> > On Mar 20, 3:39 pm, Ruben Safir <> wrote:
    >> >> On Sun, 20 Mar 2011 12:03:16 +0000, Paul wrote:
    >> >> > You'd be safer to use '\0' to null-initialise an unkown type.

    >
    >> >> That can be used for an number type, and pointer as well? That might
    >> >> be just what I'm looking for.

    >
    >> > The correct way to initialize an unknown type is to use T(). That works
    >> > for numbers, pointers and smart pointers. Beyond that, as far as the
    >> > compiler is concerned, 0, NULL, '\0' and false are all integral
    >> > constants evaluating to 0. In code, I've seen two different
    >> > conventions: use 0 systematically, for everything (except usually
    >> > false), and use 0 for numeric values, NULL for pointers, '\0' for the
    >> > nul character, and false for boolean values---in other words, behave as
    >> > if the language were logically typed.

    >
    >> But it doesn't work with a string object,

    >
    > What doesn't work with a string object. A string object doesn't
    > have a "nul" value, whatever that would mean. Regretfully,
    > string(0) (or string(NULL)) is a syntactically legal expression,
    > which results in undefined behavior.


    string could be initilased with string(0,'\0'). I don't think the character
    really matters if its empty. Also string("") would intialise it to empty.

    >
    >> but strangely enough, Victor's
    >> suggestion, which I had though about myself and rejected with out testing
    >> because of the same facts that you stated here, works perfectly for all
    >> the toyes I've tested now. It seems that '\0' is more universal and '0'

    >
    > No. '\0' and 0 have the same value.

    He didn't type 0 , he typed '0', Need to be carefull with that.

    >The first has type char,
    > the second type int. Both are null pointer constants (since
    > both are integral constant expressions evaluating to zero).
    > However, I would consider code using the first as a null point
    > defective, since it corresponds to no established convention.
    > As I said before, if you want a null pointer, use 0 or NULL
    > (depending on the local conventions). If you want a default
    > initialized value (e.g. in a template), use T(). If you want a
    > nullable value (of an arbitrary type), use Nullable<T> (or
    > Maybe<T>, or Fallible<T>, or boost::eek:ptional<T>). And if you
    > don't know what you want, figure that out first.
    >


    I'm not sure what you retruning from or where the strings are, but it should
    be easy to implement a template specialisation to despatch this
    initialisation to appropriate function.
    For example:

    /*** A couple of templates, add to your program someplace***/
    template<class T>
    struct null_value{operator T(){return T(0);}};
    template<>
    struct null_value<std::string>{operator std::string(){return
    std::string("");}};
    /**** Make sure the temple names dont clash if you put these inside another
    template ****/
    /*** use the string(0, '\0') form of intialisation or anything you want for
    strings. *****/


    /**Then use it like this in your class**/
    template<typename T>
    struct yourClass{
    null_value<T> nv; /*create a null_value object of suitable type for your
    class instanciation.*/
    null_value<T> get_null_value(){return nv;} /*use it like this to return it
    from a function*/
    };


    /**Test program**/
    int main(){
    D<std::string> d1;
    D<int> d2;

    std::string s("not empty");
    std::cout<< s << std::endl;
    s= d1.get_null_value();
    std::cout<< s << std::endl;

    int x = 5;
    std::cout<<x<<std::endl;
    x=d2.get_null_value();
    std::cout<<x<<std::endl;
    }




    It seems to work but I haven't thoroughly tested it.

    HTH.
     
    Paul, Mar 22, 2011
    #8
  9. Paul

    James Kanze Guest

    On Mar 22, 2:31 am, Ruben Safir <> wrote:
    > On Mon, 21 Mar 2011 17:44:08 -0700, James Kanze wrote:
    > > What doesn't work with a string object.


    > string mystring = 0; returns a compiler error, "Ambiguous operator= of
    > some sort".


    As will vector<char> x = 0, or just about any other such type.

    I've lost track of the context: if it is just to provide a
    default value in a template, T() works for every type which has
    a default constructor. If it is to create a "nullable" type,
    then Fallible, Maybe, optional or what ever you call the class
    in your tool kit is the solution.

    > Now a char * mystring = 0; doesn't have this problem,
    > although casting it is likely more appropriate.


    I'm not sure what the problem is.

    > But when I'm creating a template, I'm not sure what my type
    > might be and I really want to return null and stop the
    > function when I want to. It chokes on returning Null for
    > string types member function.


    If you want something nullable, you either have to use pointers
    (and probably dynamically allocated objects when it shouldn't be
    null), or something like Maybe or Fallible.

    --
    James Kanze
     
    James Kanze, Mar 26, 2011
    #9
  10. Paul

    James Kanze Guest

    On Mar 22, 6:48 am, "Paul" <> wrote:
    > "James Kanze" <> wrote in message


    > news:...

    [...]
    > > What doesn't work with a string object. A string object doesn't
    > > have a "nul" value, whatever that would mean. Regretfully,
    > > string(0) (or string(NULL)) is a syntactically legal expression,
    > > which results in undefined behavior.


    > string could be initilased with string(0,'\0'). I don't think
    > the character really matters if its empty. Also string("")
    > would intialise it to empty.


    As would string(). The real question is whether he wants an
    empty string, or a special null value, indicating no value
    present.

    --
    James Kanze
     
    James Kanze, Mar 26, 2011
    #10
  11. Paul

    Öö Tiib Guest

    On Mar 27, 5:24 am, Ruben Safir <> wrote:
    > On Sat, 26 Mar 2011 06:08:12 -0700, James Kanze wrote:
    > > As would string().  The real question is whether he wants an empty
    > > string, or a special null value, indicating no value present

    >
    > My real question is beginning to be why doesn't C++ have a universal
    > NULL value that every type can take as a value.  I know that this sounds
    > like a bit of sour grapes but it is esacaping me at this point why so
    > much thought has to go into returning a NULL 00000000 from a function
    > template when you don't know the datatypes before it is instantiated.
    >
    > sigh...


    Because C++ is not strictly OOP language. C++ is multi-paradigm
    language and lot of people using it for something do not care about
    OOP. So all types are not derived from some nullable "object" class
    and all these people do not pay for something they don't use.

    Other issue is that there are so lot of meanings of that "null",
    "zero", "false", "unknown", "empty", "not available", "failed",
    "default", "not set" and so on in different contexts of whole software
    industry where C++ is used. Even some fundamental types have several
    values carrying different nuances of nullness (float may be 0, NA, -
    INF and +INF).

    Assigning NULL to instance of Person class is therefore ambiguous and
    confusing in C++. People assign Person() instead and say "default-
    constructed" in contracts of their interfaces. If the value of default-
    constructed object does not carry the meaning in their context then
    they use some boost::eek:ptional<T>, Fallible<T>, Nullable<T> to be
    precise. If they do not want to be intrusive with such custom types
    then they use std::pair<T,bool> and describe precise meaning in
    contract documentation.
     
    Öö Tiib, Mar 27, 2011
    #11
  12. Paul

    Öö Tiib Guest

    On Mar 28, 12:46 am, Ruben Safir <> wrote:
    > On Sun, 27 Mar 2011 01:43:08 -0700, Öö Tiib wrote:
    > > If they do not want to be intrusive with such custom types then they use
    > > std::pair<T,bool> and describe precise meaning in contract
    > > documentation.

    >
    > Thank you.  Can you extrapolate on this?


    Well ... you may return std::make_pair(T(),false) when you don't have
    anything to return and std::make_pair(value,true) when you have a
    'value' to return. The cases when and why it may happen that you don't
    have anything to return you write into documentation.
     
    Öö Tiib, Mar 28, 2011
    #12
  13. Paul

    Öö Tiib Guest

    On Mar 28, 7:50 pm, Leigh Johnston <> wrote:
    > On 28/03/2011 17:39, Öö Tiib wrote:
    >
    > > On Mar 28, 12:46 am, Ruben Safir<>  wrote:
    > >> On Sun, 27 Mar 2011 01:43:08 -0700, Öö Tiib wrote:
    > >>> If they do not want to be intrusive with such custom types then they use
    > >>> std::pair<T,bool>  and describe precise meaning in contract
    > >>> documentation.

    >
    > >> Thank you.  Can you extrapolate on this?

    >
    > > Well ... you may return std::make_pair(T(),false) when you don't have
    > > anything to return and std::make_pair(value,true) when you have a
    > > 'value' to return. The cases when and why it may happen that you don't
    > > have anything to return you write into documentation.

    >
    > Better would be to use optional variables such as what Boost.Optional
    > provides as they don't require you to default construct the value type.


    Indeed i also said it initially. It is worth to note however that
    boost::eek:ptional is quite significant dependency. So i initially
    replied that pair is less intrusive option and so he wanted me to
    extrapolate on usage of that pair.
     
    Öö Tiib, Mar 28, 2011
    #13
  14. Paul

    James Kanze Guest

    On Mar 27, 3:24 am, Ruben Safir <> wrote:
    > On Sat, 26 Mar 2011 06:08:12 -0700, James Kanze wrote:
    > > As would string(). The real question is whether he wants an empty
    > > string, or a special null value, indicating no value present


    > My real question is beginning to be why doesn't C++ have a universal
    > NULL value that every type can take as a value.


    Because it would add to the cost of most types, isn't necessary
    in general, and is easy to implement if you need it.

    > I know that this sounds like a bit of sour grapes but it is
    > esacaping me at this point why so much thought has to go into
    > returning a NULL 00000000 from a function template when you
    > don't know the datatypes before it is instantiated.


    For historical reasons, pointers are special. They do have a
    special null value.

    --
    James Kanze
     
    James Kanze, Mar 28, 2011
    #14
  15. Paul

    James Kanze Guest

    On Mar 28, 5:39 pm, Öö Tiib <> wrote:
    > On Mar 28, 12:46 am, Ruben Safir <> wrote:


    > > On Sun, 27 Mar 2011 01:43:08 -0700, Öö Tiib wrote:
    > > > If they do not want to be intrusive with such custom types
    > > > then they use std::pair<T,bool> and describe precise
    > > > meaning in contract documentation.


    > > Thank you. Can you extrapolate on this?


    > Well ... you may return std::make_pair(T(),false) when you don't have
    > anything to return and std::make_pair(value,true) when you have a
    > 'value' to return. The cases when and why it may happen that you don't
    > have anything to return you write into documentation.


    In practice, every place I've worked at has had a Fallible type,
    which didn't require a default constructor.

    --
    James Kanze
     
    James Kanze, Mar 28, 2011
    #15
  16. Paul

    James Kanze Guest

    On Mar 28, 6:15 pm, Leigh Johnston <> wrote:
    > On 28/03/2011 18:08, Öö Tiib wrote:


    [...]
    > It is a fairly trivial exercise to roll your own optional
    > variable class (I did as I don't use Boost).


    Once you've done so, yes. For someone who's never done it,
    there are a few things that can go wrong, and which require
    non-trivial solutions in C++03, at least if you want to do it
    efficiently (no dynamic allocation, no more memory than is
    needed).

    --
    James Kanze
     
    James Kanze, Mar 28, 2011
    #16
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bob

    Problem with nulls

    Bob, Jul 2, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    331
  2. JKop
    Replies:
    3
    Views:
    479
  3. recover
    Replies:
    2
    Views:
    812
    recover
    Jul 25, 2006
  4. Alf P. Steinbach /Usenet

    Re: Returning Nulls in Templates

    Alf P. Steinbach /Usenet, Mar 20, 2011, in forum: C++
    Replies:
    7
    Views:
    266
    James Kanze
    Mar 26, 2011
  5. cczona
    Replies:
    1
    Views:
    100
    Rick DeNatale
    Mar 26, 2010
Loading...

Share This Page