From: James Kanze on
Alf P. Steinbach wrote:
> * Carlos Moreno:

> > I'm not saying that #defining private as public is the way
> > to run test protocols; I simply think that it is an
> > interesting alternative, that can be quite useful in certain
> > situations -- I wanted to know if I should expect the trick
> > to work in the general case.

> From a practical point of view I think so.

Provided he's not using private inheritance. (Even then, I'd be
surprised if he had a problem unless private inheritance was
used in the exception hierarchy. And only in exceptional cases
then.)

> From a formal point of view you're prohibited from defining a
> macro with the same name as a keyword if any standard library
> headers are included.

> An alternative is to directly support testing in the classes
> (it can be as simple as a "friend" declaration).

This is what I've done (or rather seen done) in the past. Every
class X has a declaration: friend class TestX. Anytime you want
to access a private member in the test, you just add a function
to TestX (which, of course, as a class only exists for this
reason, so we don't care that it isn't well designed:-)).

--
James Kanze (Gabi Software) email: kanze.james(a)neuf.fr
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Alf P. Steinbach on
* James Kanze:
> Alf P. Steinbach wrote:
>> * Carlos Moreno:
>
>>> I'm not saying that #defining private as public is the way
>>> to run test protocols; I simply think that it is an
>>> interesting alternative, that can be quite useful in certain
>>> situations -- I wanted to know if I should expect the trick
>>> to work in the general case.
>
>> From a practical point of view I think so.
>
> Provided he's not using private inheritance. (Even then, I'd be
> surprised if he had a problem unless private inheritance was
> used in the exception hierarchy. And only in exceptional cases
> then.)

Truth be told I didn't think of that case, thanks! :-) It's subtle.
Illustration code, checking for conversion to inaccessible base at run-time:

#include <iostream>
#include <ostream>

#if 0
# define private public
#endif

void out( char const s[] ) { std::cout << s << std::endl; }

class IsSerializable {};

class Base {};
class Derived: public Base, private IsSerializable {};


template< class A, class B >
class IsConvertibleFromTo
{
static char (&convert( ... ))[1];
static char (&convert( B const* ))[2];
static A const* a();
public:
// Fails to compile if B is an inaccessible base class of A.
enum{ yes = (sizeof( convert(a()) ) == 2) };
};

template< class A, class B >
bool isConvertibleFromTo()
{
try { throw static_cast<A const*>( 0 ); }
catch( B const* ) { return true; }
catch( ... ) { return false; }
}

int main()
{
out( IsConvertibleFromTo<Derived, Base>::yes? "B" : "No B" );
out( isConvertibleFromTo<Derived, IsSerializable>()? "S" : "No
S" );
}

Change the "#if 0" to "#if 1" and the output of the program is changed.

Now the question for us language definition nit-pickers (I currently
doubt that my question has practical value),

* How can we can we check for conversion to an inaccessible base class
at compile time rather than run time?

Additional question: can this have practical value?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Ulrich Eckhardt on
Carlos Moreno wrote:
> What I have in mind is debugging/testing (QA kind of
> testing). Having client code (the "test protocol")
> access to private data members gives you more flexibilty
> in terms of easily creating test case scenarios.
[dangers of various ways of changing private to public]

Carlos, you could for every class Foo have a friend class
Foo_UnitTest, which requires neither hacks nor changes to
any code.

Uli



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: wade on

Carlos Moreno wrote:
> Say that I have a C++ program that consists only of perfectly
> valid C++ code (in other words, the program compiles and does
> not invoke undefined behaviour).
>
> If I now replace every single instance of the keyword private
> with the keyword public (and I change *nothing else*), would
> the behaviour of my program change? That is, in practical
> terms, should I expect the behaviour of my program to change
> when compiled with an *actual* compiler that is reasonably
> compliant and reasonably high-quality?

This was discussed in comp.std.c++ under a topic titled "Q: private
inheritance and ambigious names".

In addition to changed "catch" behavior, you can get different runtime
dynamic_cast behavior (dynamic cast that would fail with private will
now succeed).

Also, the following may be legal (I'm not entirely sure).
#define foo x##private
If it is legal, changing private to public might change either run-time
or compile-time behavior.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Jiang on
Ulrich Eckhardt wrote:
> Carlos Moreno wrote:
> > What I have in mind is debugging/testing (QA kind of
> > testing). Having client code (the "test protocol")
> > access to private data members gives you more flexibilty
> > in terms of easily creating test case scenarios.
> [dangers of various ways of changing private to public]
>
> Carlos, you could for every class Foo have a friend class
> Foo_UnitTest, which requires neither hacks nor changes to
> any code.
>

Well, since we can not add friend class Foo_UnitTest without
touch the class Foo, the above method is quite expensive, isn't it?
Also it is possible that someone will use the class Foo_UnitTest
for other purposes.

BTW I really do not see why the replacement is necessary.

1. For debugging:

Since the debugger is part of the implementation, the access
control should not be an issue. All the unspecified behaviors
will become perfectly well-defined behaviors, provided we
stay with the same compiler/debugger.

2. For unit testing:

Also I do not see the benefits for unit testing while all the objects
will be teared up. All we need to test are the public interfaces
and internal state probing will introduce unnecessary
dependencies between the test-cases and classes.
Logger/analyzer utilities can be used if the internal states are
really necessary.

Or, I missed something important for testing?


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]