Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #13324 > unrolled thread
| Started by | ales.pergl@gmail.com |
|---|---|
| First post | 2012-01-13 04:48 -0800 |
| Last post | 2012-01-13 15:19 +0000 |
| Articles | 15 — 6 participants |
Back to article view | Back to comp.lang.c++
Typedef of inaccessible type ales.pergl@gmail.com - 2012-01-13 04:48 -0800
Re: Typedef of inaccessible type "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2012-01-13 15:07 +0100
Re: Typedef of inaccessible type ales.pergl@gmail.com - 2012-01-13 07:00 -0800
Re: Typedef of inaccessible type "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2012-01-13 16:52 +0100
Re: Typedef of inaccessible type ales.pergl@gmail.com - 2012-01-16 07:19 -0800
Re: Typedef of inaccessible type jgk@panix.com (Joe keane) - 2012-01-16 16:13 +0000
Re: Typedef of inaccessible type Markku Linnoskivi <markku.linnoskivi@gmail.com> - 2012-01-13 06:09 -0800
Re: Typedef of inaccessible type Victor Bazarov <v.bazarov@comcast.invalid> - 2012-01-13 10:54 -0500
Re: Typedef of inaccessible type Leigh Johnston <leigh@i42.co.uk> - 2012-01-13 14:32 +0000
Re: Typedef of inaccessible type Leigh Johnston <leigh@i42.co.uk> - 2012-01-13 14:38 +0000
Re: Typedef of inaccessible type "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2012-01-13 15:46 +0100
Re: Typedef of inaccessible type Leigh Johnston <leigh@i42.co.uk> - 2012-01-13 14:53 +0000
Re: Typedef of inaccessible type ales.pergl@gmail.com - 2012-01-13 06:42 -0800
Re: Typedef of inaccessible type Leigh Johnston <leigh@i42.co.uk> - 2012-01-13 15:04 +0000
Re: Typedef of inaccessible type Leigh Johnston <leigh@i42.co.uk> - 2012-01-13 15:19 +0000
| From | ales.pergl@gmail.com |
|---|---|
| Date | 2012-01-13 04:48 -0800 |
| Subject | Typedef of inaccessible type |
| Message-ID | <29510730.1476.1326458883399.JavaMail.geo-discussion-forums@yqni15> |
When I have multiple nested classes, I find it unnecessarily verbose to spell out the fully qualified name of the most nested class when defining its members.
So I'm looking for a way to define an alias for the fully qualified class name. Like this:
// in header
class A {
class B {
class C {
void DoStuff();
};
};
};
// in cpp
typedef A::B::C C; // error, A::B::C is inacessible in this context
void C::DoStuff() {} // would love to be able to shorten the class name
The problem is, the above doesn't compile, because C is not accessible from global scope. The easiest workaround is to define a macro instead of a typedef:
#define C A::B::C
Does anybody know of a better way, without using the preprocessor?
Thanks.
[toc] | [next] | [standalone]
| From | "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| Date | 2012-01-13 15:07 +0100 |
| Message-ID | <jepds4$tth$1@dont-email.me> |
| In reply to | #13324 |
On 13.01.2012 13:48, ales.pergl@gmail.com wrote:
> When I have multiple nested classes, I find it unnecessarily verbose to spell out the fully qualified name of the most nested class when defining its members.
> So I'm looking for a way to define an alias for the fully qualified class name. Like this:
>
> // in header
> class A {
> class B {
> class C {
> void DoStuff();
> };
> };
> };
You can always replace nested classes with friendships etc.
I suggest you try that.
To see what the above really means.
> // in cpp
> typedef A::B::C C; // error, A::B::C is inacessible in this context
But if you make it accessible in some way, then you would be breaking
the rules you have elaborately set up with the class nesting.
> void C::DoStuff() {} // would love to be able to shorten the class name
>
> The problem is, the above doesn't compile, because C is not accessible from
> global scope. The easiest workaround is to define a macro instead of a typedef:
>
> #define C A::B::C
>
> Does anybody know of a better way, without using the preprocessor?
You can always confer friendship to some class that can then provide
typedefs.
But then you would be exposing what you have gone to pains to make
inacessible.
There's nothing wrong with using the preprocessor in a sensible way,
like in your case, with the effect confined within a separately compiled
file.
Cheers & hth.,
- Alf
[toc] | [prev] | [next] | [standalone]
| From | ales.pergl@gmail.com |
|---|---|
| Date | 2012-01-13 07:00 -0800 |
| Message-ID | <2860857.953.1326466829576.JavaMail.geo-discussion-forums@vbtv21> |
| In reply to | #13326 |
> But if you make it accessible in some way, then you would be breaking > the rules you have elaborately set up with the class nesting. Naturally, I want to expose the type names only to the limited scope of the .cpp file where member definitions reside. So I'm not trying to void my elaborate privilege setup. ;) > You can always confer friendship to some class that can then provide > typedefs. I could do that, but that would require me to put in the header file what are essentially implementation details of the classes. Furthermore, it would not bring many benefits with regard to code verbosity/readability. > But then you would be exposing what you have gone to pains to make > inacessible. ... but only to the friendly class, which would be OK. But again, it wouldn't be less verbose nor more readable. > There's nothing wrong with using the preprocessor in a sensible way, > like in your case, with the effect confined within a separately compiled > file. I agree.
[toc] | [prev] | [next] | [standalone]
| From | "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| Date | 2012-01-13 16:52 +0100 |
| Message-ID | <jepjvt$42v$1@dont-email.me> |
| In reply to | #13333 |
On 13.01.2012 16:00, ales.pergl@gmail.com wrote:
>> But if you make it accessible in some way, then you would be breaking
>> the rules you have elaborately set up with the class nesting.
>
> Naturally, I want to expose the type names only to the limited scope of the .cpp file where member definitions reside. So I'm not trying to void my elaborate privilege setup. ;)
>
>> You can always confer friendship to some class that can then provide
>> typedefs.
>
> I could do that, but that would require me to put in the header file what are essentially implementation details of the classes. Furthermore, it would not bring many benefits with regard to code verbosity/readability.
>
>> But then you would be exposing what you have gone to pains to make
>> inacessible.
>
> ... but only to the friendly class, which would be OK. But again, it wouldn't
> be less verbose nor more readable.
I'm sorry, I'm too much accustomed to pure header modules.
In your case, with separate compilation, it is "the" solution.
<code>
class ClassA
{
friend class Class;
class ClassB
{
friend class Class;
class ClassC
{
public:
void doStuff();
};
};
};
// In implementation file:
struct Class { typedef ClassA::ClassB::ClassC C; };
typedef Class N;
void N::C::doStuff() {}
</code>
>
>> There's nothing wrong with using the preprocessor in a sensible way,
>> like in your case, with the effect confined within a separately compiled
>> file.
>
> I agree.
I think if I had to do this, if it was a requirement to have such nested
classes, then I'd use the preprocessor to simplify the implementation.
But typedef'ing works also, as shown above.
Well, except for constructors and destructors. There, the macro approach
really has the edge. ;-)
Cheers & hth.,
- Alf
[toc] | [prev] | [next] | [standalone]
| From | ales.pergl@gmail.com |
|---|---|
| Date | 2012-01-16 07:19 -0800 |
| Message-ID | <16049260.2342.1326727184057.JavaMail.geo-discussion-forums@vby1> |
| In reply to | #13336 |
>
> class ClassA
> {
> friend class Class;
>
> class ClassB
> {
> friend class Class;
>
> class ClassC
> {
> public:
> void doStuff();
> };
> };
> };
>
Interestingly enough, this has its own issues. With this approach, ClassA (and ClassB) is blindly giving friendship to any class Class. I'm not entirely sure what the standard says about this, but I've tested with VC10 that if I include this class declaration in two different modules where each defines its own class Class, the linker doesn't complain about any naming issues and both "Class"es joyfully access ClassA's private members. Possibly it's because as long as class Class is fully defined and kept private to a module, there's no ambiguity from the linker's point of view.
Seems to me that macros really win this one, hands down. :)
[toc] | [prev] | [next] | [standalone]
| From | jgk@panix.com (Joe keane) |
|---|---|
| Date | 2012-01-16 16:13 +0000 |
| Message-ID | <jf1ib7$729$1@reader1.panix.com> |
| In reply to | #13333 |
In article <2860857.953.1326466829576.JavaMail.geo-discussion-forums@vbtv21>, <comp.lang.c++@googlegroups.com> wrote: >I could do that, but that would require me to put in the header file >what are essentially implementation details of the classes. Furthermore, >it would not bring many benefits with regard to code >verbosity/readability. You can also create *two* header files, one for all the clients of your classes, and one that's only included by your implementation file(s).
[toc] | [prev] | [next] | [standalone]
| From | Markku Linnoskivi <markku.linnoskivi@gmail.com> |
|---|---|
| Date | 2012-01-13 06:09 -0800 |
| Message-ID | <e5e4b9fa-8619-4548-9e86-9987b5b99129@t30g2000vbx.googlegroups.com> |
| In reply to | #13324 |
On 13 tammi, 14:48, ales.pe...@gmail.com wrote:
> When I have multiple nested classes, I find it unnecessarily verbose to spell out the fully qualified name of the most nested class when defining its members.
> So I'm looking for a way to define an alias for the fully qualified class name. Like this:
>
> // in header
> class A {
> class B {
> class C {
> void DoStuff();
> };
> };
> };
>
> // in cpp
> typedef A::B::C C; // error, A::B::C is inacessible in this context
>
> void C::DoStuff() {} // would love to be able to shorten the class name
>
> The problem is, the above doesn't compile, because C is not accessible from global scope. The easiest workaround is to define a macro instead of a typedef:
>
> #define C A::B::C
>
> Does anybody know of a better way, without using the preprocessor?
>
> Thanks.
The class default visibility is private, so the classes B and C are
not accessible from out side, even if you give the fully qualified
name. So define the classes in public visibility and the typedef
works. And DO NOT use a define like that! That will replace all
occurances of capital C with the given string and cause all kinds of
hard to understand errors.
[toc] | [prev] | [next] | [standalone]
| From | Victor Bazarov <v.bazarov@comcast.invalid> |
|---|---|
| Date | 2012-01-13 10:54 -0500 |
| Message-ID | <jepk4h$3da$1@dont-email.me> |
| In reply to | #13327 |
On 1/13/2012 9:09 AM, Markku Linnoskivi wrote:
> On 13 tammi, 14:48, ales.pe...@gmail.com wrote:
>> When I have multiple nested classes, I find it unnecessarily verbose to spell out the fully qualified name of the most nested class when defining its members.
>> So I'm looking for a way to define an alias for the fully qualified class name. Like this:
>>
>> // in header
>> class A {
>> class B {
>> class C {
>> void DoStuff();
>> };
>> };
>> };
>>
>> // in cpp
>> typedef A::B::C C; // error, A::B::C is inacessible in this context
>>
>> void C::DoStuff() {} // would love to be able to shorten the class name
>>
>> The problem is, the above doesn't compile, because C is not accessible from global scope. The easiest workaround is to define a macro instead of a typedef:
>>
>> #define C A::B::C
>>
>> Does anybody know of a better way, without using the preprocessor?
>>
>> Thanks.
>
>
> The class default visibility is private, so the classes B and C are
> not accessible from out side, even if you give the fully qualified
> name. So define the classes in public visibility and the typedef
> works. And DO NOT use a define like that! That will replace all
> occurances of capital C
No, only occurrences where C is a complete token. For instance, in the
token Class, the 'C' is not going to be replaced to yield A::B::Class.
> with the given string and cause all kinds of
> hard to understand errors.
I am fairly certain that the OP doesn't have real classes named A, B and
C...
V
--
I do not respond to top-posted replies, please don't ask
[toc] | [prev] | [next] | [standalone]
| From | Leigh Johnston <leigh@i42.co.uk> |
|---|---|
| Date | 2012-01-13 14:32 +0000 |
| Message-ID | <QcudnVttu97l3Y3SnZ2dnUVZ8rKdnZ2d@giganews.com> |
| In reply to | #13324 |
On 13/01/2012 12:48, ales.pergl@gmail.com wrote:
> When I have multiple nested classes, I find it unnecessarily verbose to spell out the fully qualified name of the most nested class when defining its members.
> So I'm looking for a way to define an alias for the fully qualified class name. Like this:
>
> // in header
> class A {
> class B {
> class C {
> void DoStuff();
> };
> };
> };
>
> // in cpp
> typedef A::B::C C; // error, A::B::C is inacessible in this context
>
> void C::DoStuff() {} // would love to be able to shorten the class name
>
> The problem is, the above doesn't compile, because C is not accessible from global scope. The easiest workaround is to define a macro instead of a typedef:
>
> #define C A::B::C
>
> Does anybody know of a better way, without using the preprocessor?
class A
{
class B
{
class C
{
public:
static void DoStuff() {}
};
public:
typedef C nested_type;
};
public:
typedef B::nested_type nested_type;
};
typedef A::nested_type C;
int main()
{
C::DoStuff();
}
HTH.
/Leigh
[toc] | [prev] | [next] | [standalone]
| From | Leigh Johnston <leigh@i42.co.uk> |
|---|---|
| Date | 2012-01-13 14:38 +0000 |
| Message-ID | <cYGdnTCuOexK3I3SnZ2dnUVZ8nWdnZ2d@giganews.com> |
| In reply to | #13328 |
On 13/01/2012 14:32, Leigh Johnston wrote:
> On 13/01/2012 12:48, ales.pergl@gmail.com wrote:
>> When I have multiple nested classes, I find it unnecessarily verbose
>> to spell out the fully qualified name of the most nested class when
>> defining its members.
>> So I'm looking for a way to define an alias for the fully qualified
>> class name. Like this:
>>
>> // in header
>> class A {
>> class B {
>> class C {
>> void DoStuff();
>> };
>> };
>> };
>>
>> // in cpp
>> typedef A::B::C C; // error, A::B::C is inacessible in this context
>>
>> void C::DoStuff() {} // would love to be able to shorten the class name
>>
>> The problem is, the above doesn't compile, because C is not accessible
>> from global scope. The easiest workaround is to define a macro instead
>> of a typedef:
>>
>> #define C A::B::C
>>
>> Does anybody know of a better way, without using the preprocessor?
>
> class A
> {
> class B
> {
> class C
> {
> public:
> static void DoStuff() {}
> };
> public:
> typedef C nested_type;
> };
> public:
> typedef B::nested_type nested_type;
> };
>
> typedef A::nested_type C;
>
> int main()
> {
> C::DoStuff();
> }
>
My answer should have been:
class A
{
class B
{
class C
{
public:
void DoStuff();
};
public:
typedef C nested_type;
};
public:
typedef B::nested_type nested_type;
};
typedef A::nested_type C;
void C::DoStuff()
{
}
int main()
{
}
HTH.
/Leigh
[toc] | [prev] | [next] | [standalone]
| From | "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| Date | 2012-01-13 15:46 +0100 |
| Message-ID | <jepg5d$b7q$1@dont-email.me> |
| In reply to | #13329 |
On 13.01.2012 15:38, Leigh Johnston wrote:
> On 13/01/2012 14:32, Leigh Johnston wrote:
>> On 13/01/2012 12:48, ales.pergl@gmail.com wrote:
>>> When I have multiple nested classes, I find it unnecessarily verbose
>>> to spell out the fully qualified name of the most nested class when
>>> defining its members.
>>> So I'm looking for a way to define an alias for the fully qualified
>>> class name. Like this:
>>>
>>> // in header
>>> class A {
>>> class B {
>>> class C {
>>> void DoStuff();
>>> };
>>> };
>>> };
>>>
>>> // in cpp
>>> typedef A::B::C C; // error, A::B::C is inacessible in this context
>>>
>>> void C::DoStuff() {} // would love to be able to shorten the class name
>>>
>>> The problem is, the above doesn't compile, because C is not accessible
>>> from global scope. The easiest workaround is to define a macro instead
>>> of a typedef:
>>>
>>> #define C A::B::C
>>>
>>> Does anybody know of a better way, without using the preprocessor?
>>
>> class A
>> {
>> class B
>> {
>> class C
>> {
>> public:
>> static void DoStuff() {}
>> };
>> public:
>> typedef C nested_type;
>> };
>> public:
>> typedef B::nested_type nested_type;
>> };
>>
>> typedef A::nested_type C;
>>
>> int main()
>> {
>> C::DoStuff();
>> }
>>
>
> My answer should have been:
>
> class A
> {
> class B
> {
> class C
> {
> public:
> void DoStuff();
> };
> public:
> typedef C nested_type;
> };
> public:
> typedef B::nested_type nested_type;
> };
>
> typedef A::nested_type C;
>
> void C::DoStuff()
> {
> }
>
> int main()
> {
> }
Tip: if you select all the text in Thunderbird (e.g. via [Ctrl A])
before hitting "Reply", then it seems to preserve indents.
Anyway, the above ends up first making classes inaccessible, possibly
for some good reason, and then making them accessible via the typedefs.
Instead they could just have been made public in the first place.
An alternative is to use a namespace like `detail` (a convention used in
Boost), and define a class there that can provide typedefs. It still
technically exposes the classes that should be inaccessible, but
provides a marginal measure of protection via Python-like convention.
The point is after all not to protect against a determined hacker, but
to protect against inadvertent usage.
I tried to explain this in my original answer in this thread.
Cheers,
- Alf
[toc] | [prev] | [next] | [standalone]
| From | Leigh Johnston <leigh@i42.co.uk> |
|---|---|
| Date | 2012-01-13 14:53 +0000 |
| Message-ID | <p5GdnXwGQsPv2I3SnZ2dnUVZ7smdnZ2d@giganews.com> |
| In reply to | #13330 |
On 13/01/2012 14:46, Alf P. Steinbach wrote:
> On 13.01.2012 15:38, Leigh Johnston wrote:
>> On 13/01/2012 14:32, Leigh Johnston wrote:
>>> On 13/01/2012 12:48, ales.pergl@gmail.com wrote:
>>>> When I have multiple nested classes, I find it unnecessarily verbose
>>>> to spell out the fully qualified name of the most nested class when
>>>> defining its members.
>>>> So I'm looking for a way to define an alias for the fully qualified
>>>> class name. Like this:
>>>>
>>>> // in header
>>>> class A {
>>>> class B {
>>>> class C {
>>>> void DoStuff();
>>>> };
>>>> };
>>>> };
>>>>
>>>> // in cpp
>>>> typedef A::B::C C; // error, A::B::C is inacessible in this context
>>>>
>>>> void C::DoStuff() {} // would love to be able to shorten the class name
>>>>
>>>> The problem is, the above doesn't compile, because C is not accessible
>>>> from global scope. The easiest workaround is to define a macro instead
>>>> of a typedef:
>>>>
>>>> #define C A::B::C
>>>>
>>>> Does anybody know of a better way, without using the preprocessor?
>>>
>>> class A
>>> {
>>> class B
>>> {
>>> class C
>>> {
>>> public:
>>> static void DoStuff() {}
>>> };
>>> public:
>>> typedef C nested_type;
>>> };
>>> public:
>>> typedef B::nested_type nested_type;
>>> };
>>>
>>> typedef A::nested_type C;
>>>
>>> int main()
>>> {
>>> C::DoStuff();
>>> }
>>>
>>
>> My answer should have been:
>>
>> class A
>> {
>> class B
>> {
>> class C
>> {
>> public:
>> void DoStuff();
>> };
>> public:
>> typedef C nested_type;
>> };
>> public:
>> typedef B::nested_type nested_type;
>> };
>>
>> typedef A::nested_type C;
>>
>> void C::DoStuff()
>> {
>> }
>>
>> int main()
>> {
>> }
>
> Tip: if you select all the text in Thunderbird (e.g. via [Ctrl A])
> before hitting "Reply", then it seems to preserve indents.
>
> Anyway, the above ends up first making classes inaccessible, possibly
> for some good reason, and then making them accessible via the typedefs.
>
> Instead they could just have been made public in the first place.
Correct; my mistake.
/Leigh
[toc] | [prev] | [next] | [standalone]
| From | ales.pergl@gmail.com |
|---|---|
| Date | 2012-01-13 06:42 -0800 |
| Message-ID | <12693552.943.1326465772190.JavaMail.geo-discussion-forums@vbtv21> |
| In reply to | #13328 |
> int main()
> {
> C::DoStuff();
> }
I am not trying to call DoStuff() from the outside. It is intentionally private to the C class. I just want to make the function definition (i.e. implementation) less verbose.
[toc] | [prev] | [next] | [standalone]
| From | Leigh Johnston <leigh@i42.co.uk> |
|---|---|
| Date | 2012-01-13 15:04 +0000 |
| Message-ID | <N8KdnUTnO7iR1Y3SnZ2dnUVZ8gmdnZ2d@giganews.com> |
| In reply to | #13331 |
On 13/01/2012 14:42, ales.pergl@gmail.com wrote:
>> int main()
>> {
>> C::DoStuff();
>> }
>
> I am not trying to call DoStuff() from the outside. It is intentionally private to the C class. I just want to make the function definition (i.e. implementation) less verbose.
Yeah see my other reply even if it is wrong (as Alf pointed out).
Short answer: don't try to make function/class/variable names
artificially short; this is similar to the "don't use 'using namespace
std;'" argument because some people erroneously think that the 'std::'
prefix is too verbose; it isn't.
Artificially shortening function/class/variable names effectively
reduces the meaning that those names can convey; source code should be
as self-documenting as possible.
/Leigh
[toc] | [prev] | [next] | [standalone]
| From | Leigh Johnston <leigh@i42.co.uk> |
|---|---|
| Date | 2012-01-13 15:19 +0000 |
| Message-ID | <QoSdnahBiaHk1o3SnZ2dnUVZ8mqdnZ2d@giganews.com> |
| In reply to | #13334 |
On 13/01/2012 15:04, Leigh Johnston wrote:
> On 13/01/2012 14:42, ales.pergl@gmail.com wrote:
>>> int main()
>>> {
>>> C::DoStuff();
>>> }
>>
>> I am not trying to call DoStuff() from the outside. It is
>> intentionally private to the C class. I just want to make the function
>> definition (i.e. implementation) less verbose.
>
> Yeah see my other reply even if it is wrong (as Alf pointed out).
>
> Short answer: don't try to make function/class/variable names
> artificially short; this is similar to the "don't use 'using namespace
> std;'" argument because some people erroneously think that the 'std::'
> prefix is too verbose; it isn't.
>
> Artificially shortening function/class/variable names effectively
> reduces the meaning that those names can convey; source code should be
> as self-documenting as possible.
Of course if you don't speak English which tends to be the de facto
language used in programming you could argue that short symbolic names
are better... :)
/Leigh
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c++
csiph-web