Friend declaration not accepted by MSVC

Discussion in 'C++' started by Alf P. Steinbach, Aug 12, 2009.

  1. In the code below the commented friend declaration is not accepted by MSVC 7.1.


    <code>
    // Copyright (c) Alf P. Steinbach, 2009.
    #ifndef PROGROCK_CPPX_POINTERS_ZPTR_H
    #define PROGROCK_CPPX_POINTERS_ZPTR_H
    // #include <progrock/cppx/pointers/ZPtr.h>

    #include <progrock/cppx/no_sillywarnings_please.h>

    #include <progrock/cppx/exception_util.h> // throwX
    #include <progrock/cppx/static_assert.h> // CPPX_IS_OVERRIDE_OFxxx

    #include <assert.h>
    #include <memory>


    namespace progrock{ namespace cppx{

    //TODO: Implement for real.

    template< class T > class ZPtr;


    namespace zptr{ class Referent; class Callback; }

    class ZPtrMicrosoftVisualCppWorkaround
    {
    template< class T > friend class ZPtr;
    private:
    static void deleteSelfNoCallback( zptr::Referent& r );

    template< class T >
    static T* create( zptr::Callback& aCallback )
    { return new T( aCallback ); }

    template< class T, class A1 >
    static T* create( zptr::Callback& aCallback, A1 const& a1 )
    { return new T( aCallback, a1 ); }

    template< class T, class A1, class A2 >
    static T* create( zptr::Callback& aCallback, A1 const& a1, A2 const& a2 )
    { return new T( aCallback, a1, a2 ); }

    template< class T, class A1, class A2, class A3 >
    static T* create( zptr::Callback& aCallback, A1 const& a1, A2 const&
    a2, A3 const& a3 )
    { return new T( aCallback, a1, a2, a3 ); }
    };


    namespace zptr {
    class XThrower
    {
    public:
    typedef std::auto_ptr<XThrower> AutoPtr;

    virtual ~XThrower() {}

    virtual bool throwX() const
    {
    return cppx::throwX( "cppx::ZPtr: referent has been destroyed" );
    }
    };

    class Callback
    {
    public:
    virtual ~Callback() {}
    virtual void destroyAnyCompleteMeAndSetAccessX( XThrower::AutoPtr )
    = 0;
    };

    class Referent
    {
    //template< class T > friend class cppx::ZPtr;
    friend class ZPtrMicrosoftVisualCppWorkaround; // MSVC 7.1 can't
    handle the direct friend.
    typedef Referent ThisClass;

    private:
    Callback* myCallback;

    Referent( ThisClass const& ); // No such.
    ThisClass& operator=( ThisClass const& ); // No such.

    void deleteSelfNoCallback()
    {
    delete this;
    }

    static void* operator new( size_t nBytes )
    {
    return ::new char[nBytes];
    }

    static void operator delete( void* p )
    {
    ::delete[] static_cast<char*>( p );
    }

    protected:
    virtual ~Referent() {}

    template< class ExceptionType >
    void handleUnrecoverableFailure(
    ExceptionType const& x,
    XThrower::AutoPtr xThrower = XThrower::AutoPtr( new
    XThrower )
    )
    {
    myCallback->destroyAnyCompleteMeAndSetAccessX( xThrower );
    throw x;
    }

    public:
    Referent( Callback& aCallback ): myCallback( &aCallback ) {}
    };


    enum DefaultConstructed {};
    } // namespace zptr


    inline void ZPtrMicrosoftVisualCppWorkaround::deleteSelfNoCallback(
    zptr::Referent& r )
    {
    r.deleteSelfNoCallback();
    }


    template< typename T >
    class ZPtr
    : private zptr::Callback
    {
    typedef ZPtr ThisClass;

    private:
    T* myReferent; // 0 while the T constructs.
    zptr::XThrower::AutoPtr myXAction;

    ZPtr( ThisClass const& ); // No such.
    ThisClass& operator=( ThisClass const& ); // No such.

    void deleteReferent()
    {
    if( myReferent == 0 ) { return; }

    try
    {
    ZPtrMicrosoftVisualCppWorkaround::deleteSelfNoCallback(
    *myReferent );
    }
    catch( ... )
    {
    assert( "cppx::ZPtr: referent threw exception when deleted" &&
    false );
    }
    myReferent = 0;
    }

    virtual void destroyAnyCompleteMeAndSetAccessX( zptr::XThrower::AutoPtr
    xThrower )
    {
    CPPX_IS_OVERRIDE_OF_1ARG(
    zptr::Callback::destroyAnyCompleteMeAndSetAccessX, xThrower );
    assert( xThrower.get() != 0 );
    assert( myXAction.get() == 0 );

    deleteReferent();
    myXAction = xThrower;
    }

    public:
    ZPtr( zptr::DefaultConstructed )
    : myReferent( 0 )
    {
    myReferent = ZPtrMicrosoftVisualCppWorkaround::create<T>( *this );
    }

    template< class A1 >
    ZPtr( A1 const& a1 )
    : myReferent( 0 )
    {
    myReferent = ZPtrMicrosoftVisualCppWorkaround::create<T>( *this, a1 );
    }

    template< class A1, class A2 >
    ZPtr( A1 const& a1, A2 const& a2 )
    : myReferent( 0 )
    {
    myReferent = ZPtrMicrosoftVisualCppWorkaround::create<T>( *this,
    a1, a2 );
    }

    template< class A1, class A2, class A3 >
    ZPtr( A1 const& a1, A2 const& a2, A3 const a3 )
    : myReferent( 0 )
    {
    myReferent = ZPtrMicrosoftVisualCppWorkaround::create<T>( *this,
    a1, a2, a3 );
    }

    ~ZPtr()
    {
    deleteReferent();
    }

    bool isVoid() const
    {
    return (myReferent == 0);
    }

    void throwIfVoid() const
    {
    if( isVoid() )
    {
    assert( myXAction.get() != 0 );
    myXAction->throwX();
    assert( "Execution should never reach this point." && 0 );
    }
    }

    T* operator->() const
    {
    throwIfVoid();
    return myReferent;
    }
    };

    }} // namespace progrock::cppx

    #endif
    </code>


    I wonder if there's any better workaround than the kludge shown?

    Also, is there a problem with this friend declaration with any other
    compiler/version (the same kind of declaration worked fine with g++ and Comeau)?


    Cheers, & TIA.,

    - Alf
    Alf P. Steinbach, Aug 12, 2009
    #1
    1. Advertising

  2. Alf P. Steinbach wrote:
    > In the code below the commented friend declaration is not accepted by
    > MSVC 7.1.
    >
    >
    > <code>
    > // Copyright (c) Alf P. Steinbach, 2009.
    > #ifndef PROGROCK_CPPX_POINTERS_ZPTR_H
    > #define PROGROCK_CPPX_POINTERS_ZPTR_H
    > // #include <progrock/cppx/pointers/ZPtr.h>
    >
    > #include <progrock/cppx/no_sillywarnings_please.h>
    >
    > #include <progrock/cppx/exception_util.h> // throwX
    > #include <progrock/cppx/static_assert.h> // CPPX_IS_OVERRIDE_OFxxx
    > [..]


    FAQ 5.8.

    >
    > #endif
    > </code>
    >
    >
    > I wonder if there's any better workaround than the kludge shown?


    How about switching to Visual C++ 2008? Their express edition is free,
    don't you know?

    >
    > Also, is there a problem with this friend declaration with any other
    > compiler/version (the same kind of declaration worked fine with g++ and
    > Comeau)?


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Aug 12, 2009
    #2
    1. Advertising

  3. * Victor Bazarov:
    > Alf P. Steinbach wrote:
    >> In the code below the commented friend declaration is not accepted by
    >> MSVC 7.1.
    >>
    >>
    >> <code>
    >> // Copyright (c) Alf P. Steinbach, 2009.
    >> #ifndef PROGROCK_CPPX_POINTERS_ZPTR_H
    >> #define PROGROCK_CPPX_POINTERS_ZPTR_H
    >> // #include <progrock/cppx/pointers/ZPtr.h>
    >>
    >> #include <progrock/cppx/no_sillywarnings_please.h>
    >>
    >> #include <progrock/cppx/exception_util.h> // throwX
    >> #include <progrock/cppx/static_assert.h> // CPPX_IS_OVERRIDE_OFxxx
    >> [..]

    >
    > FAQ 5.8.


    I hope you're joking.


    >> #endif
    >> </code>
    >>
    >>
    >> I wonder if there's any better workaround than the kludge shown?

    >
    > How about switching to Visual C++ 2008? Their express edition is free,
    > don't you know?


    Don't you know that I know that?


    >> Also, is there a problem with this friend declaration with any other
    >> compiler/version (the same kind of declaration worked fine with g++
    >> and Comeau)?


    Anyways, I solved the problem by replacing

    namespace zptr {
    }

    with

    struct zptr {
    };

    which made the Microsoft compiler happy, and also better supports use in
    classes. :)


    Cheers,

    - Alf
    Alf P. Steinbach, Aug 12, 2009
    #3
  4. Alf P. Steinbach wrote:
    > * Victor Bazarov:
    >> Alf P. Steinbach wrote:
    >>> In the code below the commented friend declaration is not accepted by
    >>> MSVC 7.1.
    >>>
    >>>
    >>> <code>
    >>> // Copyright (c) Alf P. Steinbach, 2009.
    >>> #ifndef PROGROCK_CPPX_POINTERS_ZPTR_H
    >>> #define PROGROCK_CPPX_POINTERS_ZPTR_H
    >>> // #include <progrock/cppx/pointers/ZPtr.h>
    >>>
    >>> #include <progrock/cppx/no_sillywarnings_please.h>
    >>>
    >>> #include <progrock/cppx/exception_util.h> // throwX
    >>> #include <progrock/cppx/static_assert.h> //
    >>> CPPX_IS_OVERRIDE_OFxxx
    >>> [..]

    >>
    >> FAQ 5.8.

    >
    > I hope you're joking.


    No, I wasn't. If you wanted help about the code that doesn't compile,
    why didn't you provide a short *compilable* version of it? Too busy or
    too lazy to remove the irrelevant portions? Now, who's joking?

    >>> #endif
    >>> </code>
    >>>
    >>>
    >>> I wonder if there's any better workaround than the kludge shown?

    >>
    >> How about switching to Visual C++ 2008? Their express edition is
    >> free, don't you know?

    >
    > Don't you know that I know that?


    I didn't know, but I suspected. That's why I wrote "don't you know".
    You didn't answer the question though. Whatever.

    >>> Also, is there a problem with this friend declaration with any other
    >>> compiler/version (the same kind of declaration worked fine with g++
    >>> and Comeau)?

    >
    > Anyways, I solved the problem by replacing
    >
    > namespace zptr {
    > }
    >
    > with
    >
    > struct zptr {
    > };
    >
    > which made the Microsoft compiler happy, and also better supports use in
    > classes. :)


    Sounds good.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Aug 12, 2009
    #4
  5. * Victor Bazarov:
    > Alf P. Steinbach wrote:
    >> * Victor Bazarov:
    >>> Alf P. Steinbach wrote:
    >>>> In the code below the commented friend declaration is not accepted
    >>>> by MSVC 7.1.
    >>>>
    >>>>
    >>>> <code>
    >>>> // Copyright (c) Alf P. Steinbach, 2009.
    >>>> #ifndef PROGROCK_CPPX_POINTERS_ZPTR_H
    >>>> #define PROGROCK_CPPX_POINTERS_ZPTR_H
    >>>> // #include <progrock/cppx/pointers/ZPtr.h>
    >>>>
    >>>> #include <progrock/cppx/no_sillywarnings_please.h>
    >>>>
    >>>> #include <progrock/cppx/exception_util.h> // throwX
    >>>> #include <progrock/cppx/static_assert.h> //
    >>>> CPPX_IS_OVERRIDE_OFxxx
    >>>> [..]
    >>>
    >>> FAQ 5.8.

    >>
    >> I hope you're joking.

    >
    > No, I wasn't. If you wanted help about the code that doesn't compile,
    > why didn't you provide a short *compilable* version of it? Too busy or
    > too lazy to remove the irrelevant portions? Now, who's joking?


    Compared to copying and pasting the code in your editor, the work of writing a
    throwX function, like

    void throwX( char const s[] ) { throw std::runtime_error( s ); }

    is really insignificant.

    And ditto for the macro, for the purposes of compiling.

    I wouldn't want help from anyone not managing or understanding that.

    I'm sure you'd manage it, which is why I enquired whether you was joking.


    Cheers,

    - Alf
    Alf P. Steinbach, Aug 12, 2009
    #5
  6. Alf P. Steinbach wrote:
    > * Victor Bazarov:
    >> Alf P. Steinbach wrote:
    >>> * Victor Bazarov:
    >>>> Alf P. Steinbach wrote:
    >>>>> In the code below the commented friend declaration is not accepted
    >>>>> by MSVC 7.1.
    >>>>>
    >>>>>
    >>>>> <code>
    >>>>> // Copyright (c) Alf P. Steinbach, 2009.
    >>>>> #ifndef PROGROCK_CPPX_POINTERS_ZPTR_H
    >>>>> #define PROGROCK_CPPX_POINTERS_ZPTR_H
    >>>>> // #include <progrock/cppx/pointers/ZPtr.h>
    >>>>>
    >>>>> #include <progrock/cppx/no_sillywarnings_please.h>
    >>>>>
    >>>>> #include <progrock/cppx/exception_util.h> // throwX
    >>>>> #include <progrock/cppx/static_assert.h> //
    >>>>> CPPX_IS_OVERRIDE_OFxxx
    >>>>> [..]
    >>>>
    >>>> FAQ 5.8.
    >>>
    >>> I hope you're joking.

    >>
    >> No, I wasn't. If you wanted help about the code that doesn't compile,
    >> why didn't you provide a short *compilable* version of it? Too busy
    >> or too lazy to remove the irrelevant portions? Now, who's joking?

    >
    > Compared to copying and pasting the code in your editor, the work of
    > writing a throwX function, like
    >
    > void throwX( char const s[] ) { throw std::runtime_error( s ); }
    >
    > is really insignificant.
    >
    > And ditto for the macro, for the purposes of compiling.
    >
    > I wouldn't want help from anyone not managing or understanding that.
    >
    > I'm sure you'd manage it, which is why I enquired whether you was joking.


    Don't know what fly crawled up your nose today, Alf, but I don't even
    read past the inclusion of the headers names of which I don't recognize.
    If you don't want help "from anyone not managing", then I'm not
    managing, and you don't want my help.

    Why do you think you should be treated differently than anybody else
    here (by me or by anybody else)? Slack is usually cut to people when
    there is slack to be cut. I *don't have time* to fiddle with your code
    to make it compile to verify your claim of its being non-compilable.

    I guess you were able to manage without any help, though (judging how
    quickly you found a solution). Happy for you.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Aug 12, 2009
    #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. Alexander Stippler

    nested classes and friend declaration

    Alexander Stippler, Jul 2, 2003, in forum: C++
    Replies:
    1
    Views:
    383
    Victor Bazarov
    Jul 2, 2003
  2. Klaus
    Replies:
    3
    Views:
    1,060
    Klaus
    Mar 31, 2008
  3. Alf P. Steinbach
    Replies:
    7
    Views:
    607
    Paul Bibbings
    May 4, 2010
  4. Öö Tiib
    Replies:
    0
    Views:
    651
    Öö Tiib
    May 4, 2010
  5. Peter
    Replies:
    2
    Views:
    272
    Öö Tiib
    Jun 6, 2013
Loading...

Share This Page