473,385 Members | 1,192 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Safe bool idiom - protected function not accessible

In an article on the safe bool idiom
(http://www.artima.com/cppsource/safeboolP.html), Bjorn Karlsson gives
the following code (slightly modified):

class safe_bool_base {
protected:
typedef void (safe_bool_base::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}

safe_bool_base() {}
safe_bool_base(const safe_bool_base&) {}
safe_bool_base& operator=(const safe_bool_base&) {return *this;}
~safe_bool_base() {}
};

template <typename T=voidclass safe_bool : public safe_bool_base {
public:
operator bool_type() const {
return (static_cast<const T*>(this))->boolean_test()
? &safe_bool_base::this_type_does_not_support_compar isons : 0;
}
protected:
~safe_bool() {}
};
template<class safe_bool<void: public safe_bool_base {
public:
operator bool_type() const {
return boolean_test()==true ?
&safe_bool_base::this_type_does_not_support_compar isons //Error!
: 0;
}
protected:
virtual bool boolean_test() const=0;
virtual ~safe_bool() {}
};
template <typename T, typename U>
void operator==(const safe_bool<T>& lhs,const safe_bool<U>& rhs) {
lhs.this_type_does_not_support_comparisons();
return;
}

template <typename T,typename U>
void operator!=(const safe_bool<T>& lhs,const safe_bool<U>& rhs) {
lhs.this_type_does_not_support_comparisons();
return;
}

class Testable_with_virtual : public safe_bool<{
protected:
bool boolean_test() const {
return false;
}
};

class Testable_without_virtual :
public safe_bool <Testable_without_virtual{
public:
bool boolean_test() const {
return true;
}
};

This does not compile with VC8, VC7, or Comeau, but it does with EDG,
GNU, and VC6 (slightly modified further to account for
non-conformancies with void template args). The error occurs on the
line indicated by "Error!" and on Comeau reads:

"ComeauTest.c", line 26: error: protected function
"safe_bool_base::this_type_does_not_support_compar isons" (declared at
line 4) is not accessible through a "safe_bool_base" pointer or object
&safe_bool_base::this_type_does_not_support_compar isons //Error!
^

Notice that only the class template's specialization has a problem. Is
Comeau right as usual?

Cheers! --M

Dec 14 '06 #1
14 2441
mlimber wrote:
In an article on the safe bool idiom
(http://www.artima.com/cppsource/safeboolP.html), Bjorn Karlsson gives
the following code (slightly modified):

class safe_bool_base {
protected:
typedef void (safe_bool_base::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}

safe_bool_base() {}
safe_bool_base(const safe_bool_base&) {}
safe_bool_base& operator=(const safe_bool_base&) {return *this;}
~safe_bool_base() {}
};

template <typename T=voidclass safe_bool : public safe_bool_base {
public:
operator bool_type() const {
return (static_cast<const T*>(this))->boolean_test()
? &safe_bool_base::this_type_does_not_support_compar isons : 0;
}
protected:
~safe_bool() {}
};
template<class safe_bool<void: public safe_bool_base {
public:
operator bool_type() const {
return boolean_test()==true ?
&safe_bool_base::this_type_does_not_support_compar isons //Error!
: 0;
}
protected:
virtual bool boolean_test() const=0;
virtual ~safe_bool() {}
};
Change the line with the error to:

return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK

and the error should be fixed.

Greg

Dec 14 '06 #2
Greg wrote:
mlimber wrote:
In an article on the safe bool idiom
(http://www.artima.com/cppsource/safeboolP.html), Bjorn Karlsson gives
the following code (slightly modified):

class safe_bool_base {
protected:
typedef void (safe_bool_base::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}

safe_bool_base() {}
safe_bool_base(const safe_bool_base&) {}
safe_bool_base& operator=(const safe_bool_base&) {return *this;}
~safe_bool_base() {}
};

template <typename T=voidclass safe_bool : public safe_bool_base {
public:
operator bool_type() const {
return (static_cast<const T*>(this))->boolean_test()
? &safe_bool_base::this_type_does_not_support_compar isons : 0;
}
protected:
~safe_bool() {}
};
template<class safe_bool<void: public safe_bool_base {
public:
operator bool_type() const {
return boolean_test()==true ?
&safe_bool_base::this_type_does_not_support_compar isons //Error!
: 0;
}
protected:
virtual bool boolean_test() const=0;
virtual ~safe_bool() {}
};

Change the line with the error to:

return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK

and the error should be fixed.
Indeed. Now the question is, Why could the normal template class get to
that member but the explicit specialization could not?

Cheers! --M

Dec 14 '06 #3
mlimber wrote:
Greg wrote:

Change the line with the error to:

return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK

and the error should be fixed.

Indeed. Now the question is, Why could the normal template class get to
that member but the explicit specialization could not?
Neither one has access:

int main()
{
safe_bool<intsb;
}

error: 'safe_bool<T>::~safe_bool() [with T = int]' is protected

Greg

Dec 14 '06 #4
Greg wrote:
mlimber wrote:
Greg wrote:
>
Change the line with the error to:
>
return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK
>
and the error should be fixed.
Indeed. Now the question is, Why could the normal template class get to
that member but the explicit specialization could not?

Neither one has access:

int main()
{
safe_bool<intsb;
}

error: 'safe_bool<T>::~safe_bool() [with T = int]' is protected
The destructor is protected, indicating that safe_bool should only be
used as a base class. The derived classes should have full access to
the protected members of the base class, but it seems that only the
non-specialized derived class does. Any idea why (or is this one of the
rare bugs in Comeau)?

Cheers! --M

Dec 15 '06 #5

mlimber wrote:
Greg wrote:
mlimber wrote:
Greg wrote:

Change the line with the error to:

return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK

and the error should be fixed.
>
Indeed. Now the question is, Why could the normal template class get to
that member but the explicit specialization could not?
Neither one has access:

int main()
{
safe_bool<intsb;
}

error: 'safe_bool<T>::~safe_bool() [with T = int]' is protected

The destructor is protected, indicating that safe_bool should only be
used as a base class. The derived classes should have full access to
the protected members of the base class, but it seems that only the
non-specialized derived class does. Any idea why (or is this one of the
rare bugs in Comeau)?
No, Comeau is correct: a derived class does not have access to
protected members of a base class - either for the purposes of
obtaining a member pointer to one or even to use the protected member
in any kind of object expression. The only protected members that a
class has that kind of access are its own protected members and the
protected members of classes that derive from it. And that rule is in
fact the reason why changing the class of the member pointer from
safe_bool_base to safe_bool eliminates the access violation.

Therefore every member pointer above that refers to a protected member
of a base class - is an access violation waiting to happen. The actual
error is deferred of course until the code in question is instantiated.
So there is nothing about the void specialization that is any different
than the others templates - they all have the same problem.

Greg

Dec 15 '06 #6
Greg wrote:
mlimber wrote:
Greg wrote:
mlimber wrote:
Greg wrote:
>
Change the line with the error to:
>
return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK
>
and the error should be fixed.

Indeed. Now the question is, Why could the normal template class get to
that member but the explicit specialization could not?
>
Neither one has access:
>
int main()
{
safe_bool<intsb;
}
>
error: 'safe_bool<T>::~safe_bool() [with T = int]' is protected
The destructor is protected, indicating that safe_bool should only be
used as a base class. The derived classes should have full access to
the protected members of the base class, but it seems that only the
non-specialized derived class does. Any idea why (or is this one of the
rare bugs in Comeau)?

No, Comeau is correct: a derived class does not have access to
protected members of a base class - either for the purposes of
obtaining a member pointer to one or even to use the protected member
in any kind of object expression.
Can you cite the standard in this regard?
The only protected members that a
class has that kind of access are its own protected members and the
protected members of classes that derive from it.
Huh? A class can obtain a pointer to a member of a class that derives
from it? Unless you're talking only about virtual functions, you've
lost me completely.
And that rule is in
fact the reason why changing the class of the member pointer from
safe_bool_base to safe_bool eliminates the access violation.

Therefore every member pointer above that refers to a protected member
of a base class - is an access violation waiting to happen. The actual
error is deferred of course until the code in question is instantiated.
So there is nothing about the void specialization that is any different
than the others templates - they all have the same problem.
But the code given in my OP *does* instantiate both the specialized and
non-specialized versions, but only the specialized version causes the
compiler to choke.

Cheers! --M

Dec 15 '06 #7
Greg wrote:
mlimber wrote:
Greg wrote:
mlimber wrote:
Greg wrote:
>
Change the line with the error to:
>
return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK
>
and the error should be fixed.

Indeed. Now the question is, Why could the normal template class get to
that member but the explicit specialization could not?
>
Neither one has access:
>
int main()
{
safe_bool<intsb;
}
>
error: 'safe_bool<T>::~safe_bool() [with T = int]' is protected
The destructor is protected, indicating that safe_bool should only be
used as a base class. The derived classes should have full access to
the protected members of the base class, but it seems that only the
non-specialized derived class does. Any idea why (or is this one of the
rare bugs in Comeau)?

No, Comeau is correct: a derived class does not have access to
protected members of a base class - either for the purposes of
obtaining a member pointer to one or even to use the protected member
in any kind of object expression.
Can you cite the standard in this regard?
The only protected members that a
class has that kind of access are its own protected members and the
protected members of classes that derive from it.
Huh? A class can obtain a pointer to a member of a class that derives
from it? Unless you're talking only about virtual functions, you've
lost me completely.
And that rule is in
fact the reason why changing the class of the member pointer from
safe_bool_base to safe_bool eliminates the access violation.

Therefore every member pointer above that refers to a protected member
of a base class - is an access violation waiting to happen. The actual
error is deferred of course until the code in question is instantiated.
So there is nothing about the void specialization that is any different
than the others templates - they all have the same problem.
But the code given in my OP *does* instantiate both the specialized and
non-specialized versions, but only the specialized version causes the
compiler to choke.

Cheers! --M

Dec 15 '06 #8
Greg wrote:
mlimber wrote:
Greg wrote:
mlimber wrote:
Greg wrote:
>
Change the line with the error to:
>
return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK
>
and the error should be fixed.

Indeed. Now the question is, Why could the normal template class get to
that member but the explicit specialization could not?
>
Neither one has access:
>
int main()
{
safe_bool<intsb;
}
>
error: 'safe_bool<T>::~safe_bool() [with T = int]' is protected
The destructor is protected, indicating that safe_bool should only be
used as a base class. The derived classes should have full access to
the protected members of the base class, but it seems that only the
non-specialized derived class does. Any idea why (or is this one of the
rare bugs in Comeau)?

No, Comeau is correct: a derived class does not have access to
protected members of a base class - either for the purposes of
obtaining a member pointer to one or even to use the protected member
in any kind of object expression.
Can you cite the standard in this regard?
The only protected members that a
class has that kind of access are its own protected members and the
protected members of classes that derive from it.
Huh? A class can obtain a pointer to a member of a class that derives
from it? Unless you're talking only about virtual functions, you've
lost me completely.
And that rule is in
fact the reason why changing the class of the member pointer from
safe_bool_base to safe_bool eliminates the access violation.

Therefore every member pointer above that refers to a protected member
of a base class - is an access violation waiting to happen. The actual
error is deferred of course until the code in question is instantiated.
So there is nothing about the void specialization that is any different
than the others templates - they all have the same problem.
But the code given in my OP *does* instantiate both the specialized and
non-specialized versions, but only the specialized version causes the
compiler to choke.

Cheers! --M

Dec 15 '06 #9
Greg wrote:
mlimber wrote:
Greg wrote:
mlimber wrote:
Greg wrote:
>
Change the line with the error to:
>
return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK
>
and the error should be fixed.

Indeed. Now the question is, Why could the normal template class get to
that member but the explicit specialization could not?
>
Neither one has access:
>
int main()
{
safe_bool<intsb;
}
>
error: 'safe_bool<T>::~safe_bool() [with T = int]' is protected
The destructor is protected, indicating that safe_bool should only be
used as a base class. The derived classes should have full access to
the protected members of the base class, but it seems that only the
non-specialized derived class does. Any idea why (or is this one of the
rare bugs in Comeau)?

No, Comeau is correct: a derived class does not have access to
protected members of a base class - either for the purposes of
obtaining a member pointer to one or even to use the protected member
in any kind of object expression.
Can you cite the standard in this regard?
The only protected members that a
class has that kind of access are its own protected members and the
protected members of classes that derive from it.
Huh? A class can obtain a pointer to a member of a class that derives
from it? Unless you're talking only about virtual functions, you've
lost me completely.
And that rule is in
fact the reason why changing the class of the member pointer from
safe_bool_base to safe_bool eliminates the access violation.

Therefore every member pointer above that refers to a protected member
of a base class - is an access violation waiting to happen. The actual
error is deferred of course until the code in question is instantiated.
So there is nothing about the void specialization that is any different
than the others templates - they all have the same problem.
But the code given in my OP *does* instantiate both the specialized and
non-specialized versions, but only the specialized version causes the
compiler to choke.

Cheers! --M

Dec 15 '06 #10
Greg wrote:
mlimber wrote:
Greg wrote:
mlimber wrote:
Greg wrote:
>
Change the line with the error to:
>
return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK
>
and the error should be fixed.

Indeed. Now the question is, Why could the normal template class get to
that member but the explicit specialization could not?
>
Neither one has access:
>
int main()
{
safe_bool<intsb;
}
>
error: 'safe_bool<T>::~safe_bool() [with T = int]' is protected
The destructor is protected, indicating that safe_bool should only be
used as a base class. The derived classes should have full access to
the protected members of the base class, but it seems that only the
non-specialized derived class does. Any idea why (or is this one of the
rare bugs in Comeau)?

No, Comeau is correct: a derived class does not have access to
protected members of a base class - either for the purposes of
obtaining a member pointer to one or even to use the protected member
in any kind of object expression.
Can you cite the standard in this regard?
The only protected members that a
class has that kind of access are its own protected members and the
protected members of classes that derive from it.
Huh? A class can obtain a pointer to a member of a class that derives
from it? Unless you're talking only about virtual functions, you've
lost me completely.
And that rule is in
fact the reason why changing the class of the member pointer from
safe_bool_base to safe_bool eliminates the access violation.

Therefore every member pointer above that refers to a protected member
of a base class - is an access violation waiting to happen. The actual
error is deferred of course until the code in question is instantiated.
So there is nothing about the void specialization that is any different
than the others templates - they all have the same problem.
But the code given in my OP *does* instantiate both the specialized and
non-specialized versions, but only the specialized version causes the
compiler to choke.

Cheers! --M

Dec 15 '06 #11
Greg wrote:
mlimber wrote:
Greg wrote:
mlimber wrote:
Greg wrote:
>
Change the line with the error to:
>
return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK
>
and the error should be fixed.

Indeed. Now the question is, Why could the normal template class get to
that member but the explicit specialization could not?
>
Neither one has access:
>
int main()
{
safe_bool<intsb;
}
>
error: 'safe_bool<T>::~safe_bool() [with T = int]' is protected
The destructor is protected, indicating that safe_bool should only be
used as a base class. The derived classes should have full access to
the protected members of the base class, but it seems that only the
non-specialized derived class does. Any idea why (or is this one of the
rare bugs in Comeau)?

No, Comeau is correct: a derived class does not have access to
protected members of a base class - either for the purposes of
obtaining a member pointer to one or even to use the protected member
in any kind of object expression.
Can you cite the standard in this regard?
The only protected members that a
class has that kind of access are its own protected members and the
protected members of classes that derive from it.
Huh? A class can obtain a pointer to a member of a class that derives
from it? Unless you're talking only about virtual functions, you've
lost me completely.
And that rule is in
fact the reason why changing the class of the member pointer from
safe_bool_base to safe_bool eliminates the access violation.

Therefore every member pointer above that refers to a protected member
of a base class - is an access violation waiting to happen. The actual
error is deferred of course until the code in question is instantiated.
So there is nothing about the void specialization that is any different
than the others templates - they all have the same problem.
But the code given in my OP *does* instantiate both the specialized and
non-specialized versions, but only the specialized version causes the
compiler to choke.

Cheers! --M

Dec 15 '06 #12
mlimber wrote:
Greg wrote:
mlimber wrote:
Greg wrote:
mlimber wrote:
Greg wrote:

Change the line with the error to:

return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK

and the error should be fixed.
>
Indeed. Now the question is, Why could the normal template class get to
that member but the explicit specialization could not?

Neither one has access:

int main()
{
safe_bool<intsb;
}

error: 'safe_bool<T>::~safe_bool() [with T = int]' is protected
>
The destructor is protected, indicating that safe_bool should only be
used as a base class. The derived classes should have full access to
the protected members of the base class, but it seems that only the
non-specialized derived class does. Any idea why (or is this one of the
rare bugs in Comeau)?
No, Comeau is correct: a derived class does not have access to
protected members of a base class - either for the purposes of
obtaining a member pointer to one or even to use the protected member
in any kind of object expression.

Can you cite the standard in this regard?
§11.5 is the relevant section of the Standard:

"As described earlier, access to a protected member is granted because
the reference occurs in a friend or member of some class C. If the
access is to form a pointer to member (5.3.1), the
nested-name-specifier shall name C or a class derived from C. All other
accesses involve a (possibly implicit) object expression (5.2.5). In
this case, the class of the object expression shall be C or a class
derived from C."

Of course the members of an object include those members (if any) that
it inherits from any of its base classes; and for this reason we think
of "protected" access as allowing access to a class's members by its
derived classes - but strictly speaking, that view is not completely
accurate because the access to the member is always indirect - through
the derived class member - and not a direct access to the protected
member of the base class - as the error in the above program makes
clear.

Greg

Dec 15 '06 #13
Sorry about the reposting. Google was having issues.

Cheers! --M

Dec 15 '06 #14
Greg wrote:
mlimber wrote:
Greg wrote:
mlimber wrote:
Greg wrote:
mlimber wrote:
Greg wrote:
>
Change the line with the error to:
>
return boolean_test()==true ?
&safe_bool::this_type_does_not_support_comparis ons
: 0; // OK
>
and the error should be fixed.

Indeed. Now the question is, Why could the normal template class get to
that member but the explicit specialization could not?
>
Neither one has access:
>
int main()
{
safe_bool<intsb;
}
>
error: 'safe_bool<T>::~safe_bool() [with T = int]' is protected

The destructor is protected, indicating that safe_bool should only be
used as a base class. The derived classes should have full access to
the protected members of the base class, but it seems that only the
non-specialized derived class does. Any idea why (or is this one ofthe
rare bugs in Comeau)?
>
No, Comeau is correct: a derived class does not have access to
protected members of a base class - either for the purposes of
obtaining a member pointer to one or even to use the protected member
in any kind of object expression.
Can you cite the standard in this regard?

§11.5 is the relevant section of the Standard:

"As described earlier, access to a protected member is granted because
the reference occurs in a friend or member of some class C. If the
access is to form a pointer to member (5.3.1), the
nested-name-specifier shall name C or a class derived from C. All other
accesses involve a (possibly implicit) object expression (5.2.5). In
this case, the class of the object expression shall be C or a class
derived from C."

Of course the members of an object include those members (if any) that
it inherits from any of its base classes; and for this reason we think
of "protected" access as allowing access to a class's members by its
derived classes - but strictly speaking, that view is not completely
accurate because the access to the member is always indirect - through
the derived class member - and not a direct access to the protected
member of the base class - as the error in the above program makes
clear.

Greg
Ok, I get it now. Thanks for your help. BTW, the error does show up in
both versions if they are instantiated:

int main()
{
Testable_with_virtual twv;
Testable_without_virtual twov;
if( twv && twov ) return 1;
return 0;
}

Cheers! --M

Jan 3 '07 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Mikhail N. Kupchik | last post by:
Hi All. I have a question regarding Herb Sutter's idiom of implementation of operator= via nonthrowing swap() member function, to guarantee strict exception safety. The idea of the idiom is...
7
by: Gary | last post by:
I would like to make a strongly typed, sortable collection by leveraging a Framework class. I began by looking at CollectionBase but it doesn't have built-int sorting. I would prefer to derive...
9
by: Edward Diener | last post by:
Because 'friend' is not recognized in MC++, using the pImpl idiom in MC++ classes seems nearly impossible. Normally a pImpl class is a 'friend' to the class for which it supplies the private...
11
by: Kevin Prichard | last post by:
Hi all, I've recently been following the object-oriented techiques discussed here and have been testing them for use in a web application. There is problem that I'd like to discuss with you...
14
by: alainpoint | last post by:
Hello, I have the need to write the equivalent of Python class methods in C++. Chuck Allison proposes the following (http://www.artima.com/cppsource/simple.html): #include <iostream> using...
3
by: Nindi73 | last post by:
Hi, I am in need of a deep copy smart pointer (Boost doesn't provide one) which doesnt require the contained types to have a virtual copy constructor. I wrote a smart pointer class that I think...
1
by: Bo Yang | last post by:
I have read the safe bool idiom, and the author give four defect implements. But I can't find any difference between the void* and nested_class* solution. // operator void* version class...
9
by: Christian Hackl | last post by:
Hi! I've got a design question related to the combination of the NVI idiom (non-virtual interfaces, ) and popular object-oriented patterns such as Proxy or Decorator, i.e. those which have the...
3
by: andreas.zetterstrom | last post by:
I'm implementing some different c++ classes which I want to be thread safe. All these classes contain lists or arrays of some kind. I'm using protected sections to make them thread safe. The...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.