why I need explicit static_cast to const reference

Discussion in 'C++' started by Grizlyk, Jan 31, 2007.

  1. Grizlyk

    Grizlyk Guest

    I found, that I must write explicit cast from non-const reference to const
    reference.

    I have a class with member returning non-const reference to itself

    template<class A,class B,class C>
    class X
    {
    public:
    X& my_member(){return *this;}
    };


    And I have a class working with const reference on X<>

    template<class A,class B,class C>
    class Y
    {
    public:
    typedef X<A,B,C> X;

    void work(const X&, const X&);
    };

    And I have a class with typedefs

    template<class A,class B,class C>
    class Z
    {
    public:
    typedef X<A,B,C> X;
    typedef Y<A,B,C> Y;
    };


    When i try to use the classes together

    {
    Z::X x1,x2;
    Z::Y y;

    //error - does not match y.work
    y.work( x1.my_member(), x2.my_member() );

    //ok
    y.work(
    static_cast<const Z::X&>(x1.my_member()),
    static_cast<const Z::X&>(x2.my_member())
    );

    //ok
    y.work( x1, x2 );

    }


    Why "error - does not match y.work"?

    --
    Maksim A Polyanin
    Grizlyk, Jan 31, 2007
    #1
    1. Advertising

  2. Grizlyk

    Kai-Uwe Bux Guest

    Grizlyk wrote:

    > I found, that I must write explicit cast from non-const reference to const
    > reference.
    >
    > I have a class with member returning non-const reference to itself
    >
    > template<class A,class B,class C>
    > class X
    > {
    > public:
    > X& my_member(){return *this;}
    > };
    >
    >
    > And I have a class working with const reference on X<>
    >
    > template<class A,class B,class C>
    > class Y
    > {
    > public:
    > typedef X<A,B,C> X;
    >
    > void work(const X&, const X&);
    > };
    >
    > And I have a class with typedefs
    >
    > template<class A,class B,class C>
    > class Z
    > {
    > public:
    > typedef X<A,B,C> X;
    > typedef Y<A,B,C> Y;
    > };
    >
    >
    > When i try to use the classes together
    >
    > {
    > Z::X x1,x2;
    > Z::Y y;
    >
    > //error - does not match y.work
    > y.work( x1.my_member(), x2.my_member() );
    >
    > //ok
    > y.work(
    > static_cast<const Z::X&>(x1.my_member()),
    > static_cast<const Z::X&>(x2.my_member())
    > );
    >
    > //ok
    > y.work( x1, x2 );
    >
    > }
    >
    >
    > Why "error - does not match y.work"?


    I tried to put the pieces you posted together to reproduce the error. But I
    failed; the following compiles fine on my machine:


    template<class A,class B,class C>
    class X
    {
    public:
    X& my_member(){return *this;}
    };
    template<class A,class B,class C>
    class Y
    {
    public:
    typedef X<A,B,C> X;

    void work(const X&, const X&);
    };
    template<class A,class B,class C>
    class Z
    {
    public:
    typedef X<A,B,C> X;
    typedef Y<A,B,C> Y;

    void dummy () {
    X x1,x2;
    Y y;

    y.work( x1.my_member(), x2.my_member() );

    }

    };

    int main ( void ) {}


    Could you provide a small complete program that shows the error?


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Jan 31, 2007
    #2
    1. Advertising

  3. Grizlyk wrote:
    > I found, that I must write explicit cast from non-const reference to const
    > reference.
    >

    .... snipped
    >
    > Why "error - does not match y.work"?


    Works for me. It might be your compiler.

    BTW - next time, make it so I can just cun-n-paste and compile - like SO:


    template<class A,class B,class C>
    class X
    {
    public:
    X& my_member(){return *this;}
    };


    // And I have a class working with const reference on X<>

    template<class A,class B,class C>
    class Y
    {
    public:
    typedef X<A,B,C> X;

    void work(const X&, const X&) {}
    };

    // And I have a class with typedefs

    template<class A,class B,class C>
    class Z
    {
    public:
    typedef X<A,B,C> X;
    typedef Y<A,B,C> Y;
    };


    // When i try to use the classes together

    int main()
    {
    typedef Z<int,int,int> Z;
    Z::X x1,x2;
    Z::Y y;

    //error - does not match y.work
    y.work( x1.my_member(), x2.my_member() );

    //ok
    y.work(
    static_cast<const Z::X&>(x1.my_member()),
    static_cast<const Z::X&>(x2.my_member())
    );

    //ok
    y.work( x1, x2 );

    }
    Gianni Mariani, Jan 31, 2007
    #3
  4. On Jan 31, 10:42 pm, "Grizlyk" <> wrote:
    > I found, that I must write explicit cast from non-const reference to const
    > reference.
    >
    > I have a class with member returning non-const reference to itself
    >
    > template<class A,class B,class C>
    > class X
    > {
    > public:
    > X& my_member(){return *this;}
    >
    > };


    For some functions/operators it can be a good idea to declare a const-
    version:

    const X& my_member() const { return *this; }

    Whenever you have a const instance of X and call my_member() on it
    it's the const-version that will be called.

    --
    Erik Wikström
    =?iso-8859-1?q?Erik_Wikstr=F6m?=, Feb 1, 2007
    #4
  5. Grizlyk

    Grizlyk Guest

    Grizlyk wrote:
    >
    >I found, that I must write explicit cast from non-const reference to const
    >reference.
    >
    > y.work(
    > static_cast<const Z::X&>(x1.my_member()),
    > static_cast<const Z::X&>(x2.my_member())
    > );


    I was wrong, the cause of neccessary static_cast is inheritance. Insead of

    > template<class A,class B,class C>
    > class X
    > {
    > public:
    > X& my_member(){return *this;}
    > };


    I really have in "my_member()" reference to X<A,B,C> base class returned:

    template<class A,class B,class C>
    class X: public Base<A,B,C>
    {
    public:
    Base<A,B,C>& my_member(){return *this;}
    };

    So i get unexpected example of CRTP implementation - static_cast to derived
    class.

    --
    Maksim A Polyanin
    Grizlyk, Feb 1, 2007
    #5
  6. Grizlyk

    Grizlyk Guest

    Grizlyk wrote:
    >
    > So i get unexpected example of CRTP implementation - static_cast to
    > derived class.



    And I have divided classes like this

    template<class A,class B,class C>
    class Base<A,B,C>
    {
    public:
    Base<A,B,C>& my_member(){return *this;}
    };


    template<class A,class B,class C>
    class X: public Base<A,B,C>
    {
    public:
    X& my_member(){return static_cast<X&>(Base<A,B,C>::my_member());}
    };

    --
    Maksim A Polyanin
    Grizlyk, Feb 1, 2007
    #6
    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. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,762
    Smokey Grindel
    Dec 2, 2006
  2. Bo Peng
    Replies:
    11
    Views:
    1,070
    Victor Bazarov
    Oct 20, 2006
  3. Replies:
    11
    Views:
    1,089
  4. Javier
    Replies:
    2
    Views:
    548
    James Kanze
    Sep 4, 2007
  5. junyangzou
    Replies:
    13
    Views:
    247
Loading...

Share This Page