Friend declaration not accepted by MSVC

12 views
Skip to first unread message

Alf P. Steinbach

unread,
Aug 12, 2009, 10:57:29 AM8/12/09
to
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

Victor Bazarov

unread,
Aug 12, 2009, 11:20:12 AM8/12/09
to
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

Alf P. Steinbach

unread,
Aug 12, 2009, 11:52:22 AM8/12/09
to
* 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

Victor Bazarov

unread,
Aug 12, 2009, 12:31:31 PM8/12/09
to
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.

Alf P. Steinbach

unread,
Aug 12, 2009, 12:41:08 PM8/12/09
to
* 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

Victor Bazarov

unread,
Aug 12, 2009, 12:54:55 PM8/12/09
to

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.

Reply all
Reply to author
Forward
0 new messages