I have the following class:
class MyClass {
public:
MyClass( char* what ) : controlled( what ) {}
~MyClass() { delete[] controlled; }
operator char*() const { return controlled; }
operator void*() const { return controlled; }
operator bool() const { return controlled != 0; }
private:
char* controlled;
};
This is compiled with Microsoft SDK that has the following typedefs:
typedef long LONG_PTR;
typedef LONG_PTR LPARAM;
The calling code does the following:
MyClass instance( new char[1000] );
LPARAM castResult = (LPARAM)instance;
// Then we send message intending to pass the address of the buffer inside MyClass
::SendMessage( window, message, wParam, castResult );
Suddenly castResult is 1 - MyClass::operator bool() is invoked, it returns true which is converted to 1. So instead of passing the address I pass 1 into SendMessage() which leads to undefined behaviour.
But why is operator bool() invoked in the first place?
It's one of the known pitfalls of using operator bool, that is a aftershock of C inheritance. You'd definitively benefit from reading about the Safe Bool Idiom.
In general, you didn't provide any other matchable casting operator, and bool (unfortunately) is treated as a good source for arithmetic casting.
operator bool is the best match, because char* and void* can't be converted to long without an explicit cast, unlike bool:
long L1 = (void*)instance; // error
long L2 = (char*)instance; // error
long L3 = (bool)instance; // ok
You cannot implicitly cast a T* to long. But you can cast a bool to long.
So the operator bool is used.
You have to define a operator LPARAM.
Related
I am trying to get a bool value out of user defined object.
For example with float or int I can do something like
float a = 3.5
if (a) doSomething();
I want my class to look like this:
class Socket {
...
...
};
...
Socket T;
if (!T) cout << "Error occured";
else {
doStuff();
}
Of course I can define a function that returns bool (like bool isValid();) and call it directly, but I would like to know if it is possible.
In C++11, you can safely convert your type to a boolean value:
explicit operator bool() const {return isValid();}
If your compiler doesn't support that, then you could write the same thing without explicit; however, that can be a bit dangerous because it enables implicit conversions to any numeric type. Instead, you could use a hack known as the safe bool idiom:
private:
typedef void (Socket::*safe_bool)() const;
void safe_true() const {}
public:
operator safe_bool() const {return isValid() ? &Socket::safe_true : 0;}
This returns a pointer type which can't be converted into anything except bool.
Can you explain for me what the typedef here is doing and what the purpose is?
class C
{
public:
...
typedef bool (C::*implementation_defined_bool_type)(bool) const;
operator implementation_defined_bool_type() const {
return _spi ? &C::isPersistent : 0;
}
};
Can you explain for me what the typedef is doing here?
typedef bool (C::*implementation_defined_bool_type)(bool) const;
typedefs a pointer to a const member function of a type C, which takes a bool as input parameter and also returns a bool.
While,
operator implementation_defined_bool_type() const
Takes in an object of type C and returns a type implementation_defined_bool_type.
It is known as an Conversion Operator.
what is the purpose of it?
It implements the "Safe Bool Idiom", which aims to validate an object in a boolean context.
Note that the Safe Bool Idiom is obsolete with the C++11 Standard.
Good Read:
The Safe Bool Idiom
First is the code
#include <stdio.h>
typedef wchar_t* BSTR;
wchar_t hello[] = L"Hello";
class _bstr_t {
public:
operator const wchar_t*() const throw() { return hello; }
operator wchar_t*() const throw() { return hello; }
};
class container {
public:
operator _bstr_t() { return _bstr_t(); }
};
int main()
{
// This gives error (with gcc 4.5.2 at least):
// test.cpp:20:27: error: cannot convert "container" to "wchar_t*" in initialization
wchar_t *str = container();
printf("%S\n", str);
return 0;
}
The problem here is that container() can be casted to _bstr_t and then to wchar_t*, but, gcc does not.
The problem can be solved using manual cast:
wchar_t *str = (_bstr_t)container();
But what I need is to avoid manual cast, I would like gcc to figure this out automatically.
Why I need this is because the returned container type objects will be used in calls like
void Func(wchar_t* str);
Func(myObject->Container);
where I don't want to do manual casting.
I verified Visual Studio and it does not seem to support such scenario, too. Too bad, but I would be glad if someone can provide a workaround, even if for this specific case.
UPDATE: for those who suggests operator wchar_t* on the container, that was the problem in first place. This will either leak or crash when destroyed before Func() has a chance to accept the pointer.
When doing implicit conversions, there's at most one user-defined conversion that can happen. MSVC behaviour is not standard compliant in this matter.
C++11 (12.3 Conversions):
At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.
For the implicit conversion to work, container has to convert directly to wchar_t*.
It doesn't work because the class container has no operator wchar_t*(). The only solution is to add it to the container class :
#include <iostream>
typedef wchar_t* BSTR;
wchar_t hello[] = L"Hello";
class container {
public:
operator const wchar_t*() const throw() { return hello; }
operator wchar_t*() const throw() { return hello; }
};
int main()
{
// This gives error (with gcc 4.5.2 at least):
// test.cpp:20:27: ошибка: cannot convert «container» to «wchar_t*» in initialization
wchar_t *str = container();
std::wcout<<str<<std::endl;
}
You do not have a converter from wchar_t * to container that is why you get the error
class container {
public:
operator wchar_t*() { return _bstr_t(); }
};
How do I make a class in C++, when initialized, return a Boolean value when its name is invoked, but no explicit function call make, like ifstream. I want to be able to do this:
objdef anobj();
if(anobj){
//initialize check is true
}else{
//cannot use object right now
}
not just for initialization, but a check for its ability to be used.
The way istream does it is by providing an implicit conversion to void*
http://www.cplusplus.com/reference/iostream/ios/operator_voidpt/
stream output and implicit void* cast operator function invocation
Update In reaction to the comments, the Safe Bool Idiom would be a far better solution to this: (code directly taken from that page)
class Testable {
bool ok_;
typedef void (Testable::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}
public:
explicit Testable(bool b=true):ok_(b) {}
operator bool_type() const {
return ok_==true ?
&Testable::this_type_does_not_support_comparisons : 0;
}
};
template <typename T>
bool operator!=(const Testable& lhs,const T& rhs) {
lhs.this_type_does_not_support_comparisons();
return false;
}
template <typename T>
bool operator==(const Testable& lhs,const T& rhs) {
lhs.this_type_does_not_support_comparisons();
return false;
}
The article by Bjorn Karlsson contains a reusable implementation for the Safe Bool Idiom
Old sample:
For enjoyment, I still show the straight forward implementation with operator void* overloading, for clarity and also to show the problem with that:
#include <iostream>
struct myclass
{
bool m_isOk;
myclass() : m_isOk(true) { }
operator void* () const { return (void*) (m_isOk? 0x1 : 0x0); }
};
myclass instance;
int main()
{
if (instance)
std::cout << "Ok" << std::endl;
// the trouble with this:
delete instance; // no compile error !
return 0;
}
This is best accomplished using the safe bool idiom.
You provide an implicit conversion to a member-function-pointer, which allows instances of the type to be used in conditions but not implicitly convertyed to bool.
You need a (default) constructor and an operator bool()().
class X {
public:
operator bool ()const{
//... return a boolean expression
}
};
usage:
X x; // note: no brackets!
if( x ) {
....
}
You'll want to create an operator bool function (or as boost does, an unspecified_bool_type that has certain improved properties I can't recall offhand). You may also want to create operator! (For some reason I seem to recall iostreams do this too).
Is there a trick to get the safe bool idiom completely working without having to derive from a class that does the actual implementation?
With 'completely working', I mean the class having an operator allowing it to be tested as if it were a boolean but in a safe way:
MyTestableClass a;
MyOtherTestableClass b;
//this has to work
if( a );
if( b );
//this must not compile
if( a == b );
if( a < b );
int i = a;
i += b;
when using this implementation for example
struct safe_bool_thing
{
int b;
};
typedef int safe_bool_thing::* bool_type;
safe_bool( const bool b ) { return b ? &safe_bool_thing::b : 0; }
class MyTestableClass
{
operator bool_type () const { return safe_bool( someCondition ); }
}
it's almost fine, except a == b will still compile, since member pointers can be compared. The same implementation as above, but with pointer to member function instead of pointer to member variable has exactly the same problem.
Known implementations that do work perfectly (as described here for example, or the safe_bool used in boost) require that the testable class derive from a class providing the actual operator implementation.
I actually think there is no way around it, but'm not entirely sure. I tried something that looked a bit fischy but I thought it might work, yet is doesn't compile at all. Why is the compiler not allowed to see that the operator returns a safe_bool_thing, which in turn can be converted to bool() and hence be tested?
struct safe_bool_thing
{
explicit safe_bool_thing( const bool bVal ) : b( bVal ) {}
operator bool () const { return b; }
private:
const bool b;
safe_bool_thing& operator = ( const safe_bool_thing& );
bool operator == ( const safe_bool_thing& );
bool operator != ( const safe_bool_thing& );
};
class MyTestableClass
{
operator safe_bool_thing () const { return safe_bool_thing( someCondition ); }
};
MyTestableClass a;
if( a ); //conditional expression of type 'MyTestableClass' is illegal
This should work:
class MyTestableClass
{
private:
void non_comparable_type() {}
public:
typedef void (MyTestableClass::* bool_type)();
operator bool_type () const { return (someCondition ? &MyTestableClass::non_comparable_type : 0); }
};
class MyOtherTestableClass
{
private:
void non_comparable_type() {}
public:
typedef void (MyOtherTestableClass::* bool_type)();
operator bool_type () const { return (someCondition ? &MyOtherTestableClass::non_comparable_type : 0); }
};
For blocking the if (a == b) case, it depends on the fact that both types convert to incompatible pointer types.
"Why is the compiler not allowed to see"
I don't have an answer for safe bool, but I can do this bit. It's because a conversion sequence can include at most 1 user-defined conversion (13.3.3.1.2).
As for why that is - I think someone decided that it would be too hard to figure out implicit conversions if they could have arbitrarily many user-defined conversions. The difficulty it introduces is that you can't write a class with a conversion, that "behaves like built-in types". If you write a class which, used idiomatically, "spends" the one user-defined conversion, then users of that class don't have it to "spend".
Not that you could exactly match the conversion behaviour of built-in types anyway, since in general there's no way to specify the rank of your conversion to match the rank of the conversion of the type you're imitating.
Edit: A slight modification of your first version:
#define someCondition true
struct safe_bool_thing
{
int b;
};
typedef int safe_bool_thing::* bool_type;
bool_type safe_bool( const bool b ) { return b ? &safe_bool_thing::b : 0; }
class MyTestableClass
{
public:
operator bool_type () const { return safe_bool( someCondition ); }
private:
bool operator==(const MyTestableClass &rhs);
bool operator!=(const MyTestableClass &rhs);
};
int main() {
MyTestableClass a;
MyTestableClass b;
a == b;
}
a == b will not compile, because function overload resolution ignores accessibility. Accessibility is only tested once the correct function is chosen. In this case the correct function is MyTestableClass::operator==(const MyTestableClass &), which is private.
Inside the class, a == b should compile but not link.
I'm not sure if == and != are all the operators you need to overload, though, is there anything else you can do with a pointer to data member? This could get bloated. It's no better really than Bart's answer, I just mention it because your first attempt was close to working.
EDIT: Oh! I did not read your requirements correctly, so the below does not satisfy all of them.
It is easy enough without any special base class:
struct MyClass
{
int some_function () const;
typedef int (MyClass:: * unspec_bool_type) () const;
operator unspec_bool_type () const
{
return some_condition ? &MyClass::some_function : 0;
}
};
So, given suitable member variable of member function, you can impement it in just 5 lines of simple code.