Typecasting operator on simple types vs. classes

Discussion in 'C++' started by Nicolay Korslund, Sep 29, 2003.

  1. Hi! I'm having a little trouble with the typecast operator, can anybody
    help me with the rules for when the this operator is invoked?

    In the class 'Test' in the code below, the typecast operator returns a
    'mytype'. In main() I use the [] operator on 'Test'-class objects. If
    'mytype' is a pointer the [] operator works fine. But if I instead try
    to call an overloaded [] operator, the typecast operator is not invoked,
    and I get a compiler error (unless I make an explicit cast.) So does the
    'operator mytype ()' only work properly with simple types?

    Any help would be appreciated!

    Nico

    template <class mytype>
    class Test
    {
    mytype i;

    public:

    operator mytype () {return i;}
    };

    class Test2
    {
    public:
    int operator [] (int i) {return i;}
    };

    int main(void)
    {
    Test<double*> t1;
    Test<Test2> t2;

    t1[0]; // This line works fine
    t2[0]; // This line doesn't compile
    ((Test2)t2)[0]; // This also works

    return 0;
    }
     
    Nicolay Korslund, Sep 29, 2003
    #1
    1. Advertising

  2. Nikolai Borissov wrote:
    > Nicolay Korslund wrote:


    > I would suggest adding [] operator to the *Test* class, like this
    >
    > int operator[](int ind) {return i[ind];}
    >
    > Then you don't have to think about typecasting.


    Except that t1[0] returns a double and t2[0] returns an int.

    I'm thinking the other answer is a proxy class.
     
    Gianni Mariani, Sep 30, 2003
    #2
    1. Advertising

  3. Nicolay Korslund wrote:
    > Hi! I'm having a little trouble with the typecast operator, can anybody
    > help me with the rules for when the this operator is invoked?
    >
    > In the class 'Test' in the code below, the typecast operator returns a
    > 'mytype'. In main() I use the [] operator on 'Test'-class objects. If
    > 'mytype' is a pointer the [] operator works fine. But if I instead try
    > to call an overloaded [] operator, the typecast operator is not invoked,
    > and I get a compiler error (unless I make an explicit cast.) So does the
    > 'operator mytype ()' only work properly with simple types?
    >
    > Any help would be appreciated!
    >
    > Nico
    >
    > template <class mytype>
    > class Test
    > {
    > mytype i;
    >
    > public:
    >
    > operator mytype () {return i;}
    > };
    >
    > class Test2
    > {
    > public:
    > int operator [] (int i) {return i;}
    > };
    >
    > int main(void)
    > {
    > Test<double*> t1;
    > Test<Test2> t2;
    >
    > t1[0]; // This line works fine
    > t2[0]; // This line doesn't compile
    > ((Test2)t2)[0]; // This also works
    >
    > return 0;
    > }
    >


    I'm not sure why the code above does not work. There seems to be only
    one conversion operator and one operator[] definition. I looked through
    the copy of the standard I have and it is unfortunatly very wordy about
    the subject and hard to filter the relevant pieces.


    This is another version of your example that does work. (at least on gcc
    3.3.1).


    template <class mytype> class TestProxy;

    template <class mytype>
    class Test
    {
    friend class TestProxy<mytype>;
    mytype v;

    public:

    operator mytype & ()
    {
    return v;
    }

    TestProxy<mytype> operator [] (int i);

    };

    template <typename T>
    class PtrType
    {
    public:
    typedef int Type; // HACK ALERT
    };

    template <typename T>
    class PtrType<T*>
    {
    public:
    typedef T & Type;
    };

    template <class mytype> class TestProxy
    {
    public:

    Test<mytype> & m_test;
    int m_i;

    TestProxy( Test<mytype> & i_test, int i )
    : m_test( i_test ),
    m_i( i )
    {
    }

    operator typename PtrType<mytype>::Type ()
    {
    return m_test.v[m_i];
    }
    };

    template <class mytype>
    inline TestProxy<mytype> Test<mytype>::eek:perator [] (int i)
    {
    return TestProxy<mytype>( *this, i );
    }

    class Test2
    {
    public:
    int operator [] (int i)
    {
    return i;
    }

    };

    int main(void)
    {
    Test<double*> t1;
    Test<Test2> t2;

    t1[1]; // This line works fine
    int x = t2[2]; // This line doesn't compile
    ((Test2)t2)[3]; // This also works

    return 0;
    }
     
    Gianni Mariani, Sep 30, 2003
    #3
  4. Nicolay Korslund wrote:

    <SNIP>
    > In the class 'Test' in the code below, the typecast operator returns a
    > 'mytype'. In main() I use the [] operator on 'Test'-class objects. If
    > 'mytype' is a pointer the [] operator works fine. But if I instead try
    > to call an overloaded [] operator, the typecast operator is not invoked,
    > and I get a compiler error (unless I make an explicit cast.) So does the
    > 'operator mytype ()' only work properly with simple types?

    <SNIP>
    >
    > template <class mytype>
    > class Test
    > {
    > mytype i;
    >
    > public:
    >
    > operator mytype () {return i;}
    > };
    >
    > class Test2
    > {
    > public:
    > int operator [] (int i) {return i;}
    > };
    >
    > int main(void)
    > {
    > Test<double*> t1;
    > Test<Test2> t2;
    >
    > t1[0]; // This line works fine
    > t2[0]; // This line doesn't compile
    > ((Test2)t2)[0]; // This also works
    >
    > return 0;
    > }


    There is a rule that in a conversion sequence only one use-defined
    conversion operator is allowed.
    My guess is that the rule covers overloaded operators too.
    t1[0] works because there is only one use-defined conversion is involved :
    operator mytype () {return i;}
    It returns object of double* type for which built-in [] operator is defined.
    t2[0], however, casts through the above user-defined conversion to Test2
    type, which, in turn, has only use-defined [] operator. Of course, when you
    remove one of user-defined operators from implicit sequence by explicit
    typecasting, everything works: ((Test2)t2)[0]

    I would suggest adding [] operator to the *Test* class, like this

    int operator[](int ind) {return i[ind];}

    Then you don't have to think about typecasting.

    Nikolai Borissov
     
    Nikolai Borissov, Sep 30, 2003
    #4
  5. Nikolai Borissov wrote:
    > Gianni Mariani wrote:
    >
    >>Nikolai Borissov wrote:
    >>
    >>>Nicolay Korslund wrote:

    >>
    >>>I would suggest adding [] operator to the *Test* class, like this
    >>>
    >>>int operator[](int ind) {return i[ind];}
    >>>
    >>>Then you don't have to think about typecasting.

    >>
    >>Except that t1[0] returns a double and t2[0] returns an int.

    >
    >
    > That's right, because t1 and t2 are objects of different type. It's already
    > not a technical matter, rather a design one.
    > OP is supposed to know the purpose of his design. Maybe t1[] being of type
    > int and t2[] of type double is exactly what he wants.
    >
    >>I'm thinking the other answer is a proxy class.
    >>

    >
    >
    > And I'm thinking about Occum's Razor:
    >
    > "Entities must not be multiplied beyond what is necessary"


    The counter is the Mariani conjecture.

    "unneccessarily complex solutions are a product of adopting
    unneccessarily simple tools".

    Here is the orginal in English.

    If you use tools too simple for the given task you will end up with a
    solution that is more complex than neccassary.

    >
    > Here's an original Latin version:
    >
    > "Pluralitas non est ponenda sine neccesitate"
     
    Gianni Mariani, Sep 30, 2003
    #5
  6. Gianni Mariani wrote:
    > Nikolai Borissov wrote:
    > > Nicolay Korslund wrote:

    >
    > > I would suggest adding [] operator to the *Test* class, like this
    > >
    > > int operator[](int ind) {return i[ind];}
    > >
    > > Then you don't have to think about typecasting.

    >
    > Except that t1[0] returns a double and t2[0] returns an int.


    That's right, because t1 and t2 are objects of different type. It's already
    not a technical matter, rather a design one.
    OP is supposed to know the purpose of his design. Maybe t1[] being of type
    int and t2[] of type double is exactly what he wants.
    >
    > I'm thinking the other answer is a proxy class.
    >


    And I'm thinking about Occum's Razor:

    "Entities must not be multiplied beyond what is necessary"

    Here's an original Latin version:

    "Pluralitas non est ponenda sine neccesitate"

    Nikolai Borissov
     
    Nikolai Borissov, Sep 30, 2003
    #6
  7. Gianni Mariani wrote:

    > The counter is the Mariani conjecture.
    >
    > "unneccessarily complex solutions are a product of adopting
    > unneccessarily simple tools".
    >
    > Here is the orginal in English.
    >
    > If you use tools too simple for the given task you will end up with a
    > solution that is more complex than neccassary.


    Good addendum to Occum's Razor :))

    I've realized what's the problem with returning correct type.
    Should be interesting to think about it the other day (just don't have time
    now).
    I'll analyze your solution too.

    Ciao

    Nikolai Borissov
     
    Nikolai Borissov, Sep 30, 2003
    #7
  8. > I've realized what's the problem with returning correct type.
    > Should be interesting to think about it the other day (just don't have time
    > now).
    > I'll analyze your solution too.
    >


    Ok, thank you both for the help.

    Nicolay
     
    Nicolay Korslund, Sep 30, 2003
    #8
    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. =?Utf-8?B?Smlt?=

    ArrayList typecasting from binary SQL data

    =?Utf-8?B?Smlt?=, Apr 11, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    528
    Bruce Barker
    Apr 11, 2005
  2. Soren Kuula
    Replies:
    2
    Views:
    577
    Henry S. Thompson
    Dec 1, 2005
  3. Replies:
    8
    Views:
    1,371
    Victor Bazarov
    Jan 7, 2006
  4. Replies:
    5
    Views:
    353
    James Kanze
    Apr 27, 2007
  5. Zeguudo Zegudissimo
    Replies:
    4
    Views:
    497
    Zeguudo Zegudissimo
    Sep 2, 2010
Loading...

Share This Page