I have another question related to the safe bool idiom:
typedef void (Testable::*bool_type)() const; // const necessary?
void this_type_does_not_support_comparisons() const {} // const necessary?
operator bool_type() const
{
return ok_ ? &Testable::this_type_does_not_support_comparisons : 0;
}
How come the bool_type (the typedef) and this_type_does_not_support_comparisons are const?
Nobody is supposed to actually call the member function through the return pointer anyway, right?
Is const necessary here? Would operator bool_type (the member function) violate const-correctness otherwise?
The "safe bool idiom" is the technical answer to the question "i want a vehicle that is both sports car and tractor, and maybe a boat". The practical answer is not the technical answer…
That said, the problem it solves is just to give a result that is convertible to bool but not to much of anything else (otherwise an instance of the class could be passed as actual argument where e.g. the formal argument was int, say). A data pointer could be convertible to void*. A function pointer isn't, at least formally within the C++ standard (Posix is something else, practice also).
Using a member function pointer protects against accidentally calling the function, given the pointer from the safe bool operator. The const constricts it a bit, but if fate has put someone on the path of making maximum number of silly mistakes, that person might still manage to call the do-nothing function. Instead of the const I think I would just let it have an argument of a private type, where other code cannot provide such an argument, and then it doesn't have to be a silly member function type anymore.
Can look like this:
#include <stdio.h>
class Foo
{
private:
enum PrivateArg {};
typedef void (*SafeBool)( PrivateArg );
static void safeTrue( PrivateArg ) {}
bool state_;
public:
Foo( bool state ): state_( state ) {}
operator SafeBool () const
{ return (state_? &safeTrue : 0); }
};
int main()
{
if( Foo( true ) ) { printf( "true\n" ); }
if( Foo( false ) ) { printf( "false\n" ); } // No output.
//int const x1 = Foo( false ); // No compilado!
//void* const x2 = Foo( false ); // No compilado!
}
Of course, the practical answer is instead something like this:
#include <stdio.h>
class Foo
{
private:
bool isEmpty_;
public:
Foo( bool asInitiallyEmpty )
: isEmpty_( asInitiallyEmpty )
{}
bool isEmpty() const { return isEmpty_; }
};
int main()
{
if( Foo( true ).isEmpty() ) { printf( "true\n" ); }
if( Foo( false ).isEmpty() ) { printf( "false\n" ); } // No output.
//bool const x0 = Foo( false ); // No compilado!
//int const x1 = Foo( false ); // No compilado!
//void* const x2 = Foo( false ); // No compilado!
}
Summary wrt. questions asked:
How come the bool_type (the typedef) and this_type_does_not_support_comparisons are const?
Somebody didn't quite understand what they coded. Or maybe they intended to restrict the ability to call, a little. But then, pretty futile measure.
Nobody is supposed to actually call the member function through the return pointer anyway, right?
Right.
Is const necessary here?
No.
Would operator bool_type (the member function) violate const-correctness otherwise?
No.
Cheers & hth.,
8.3.5/ A cv-qualifier-seq shall only be part of the function type for
a nonstatic member function, the function type to which a pointer to
member refers, or the top-level function type of a function typedef
declaration. The effect of a cv-qualifier-seq in a function declarator
is not the same as adding cv-qualification on top of the function
type, i.e., it does not create a cv-qualified function type.
If I read correctly, you can return a pointer to non const member in a const member function. You just won't be able to call it with a non const object.
A way to forbid the calling is:
private:
struct private_
{
void this_type_does_not_support_comparisons() {}
};
public:
typedef void (private_::*bool_type)() const;
operator bool_type() const
{
return ok_ ? &private_::this_type_does_not_support_comparisons : 0;
}
Pointer to member functions can still be compared for equality. You have to write an operator== and operator!= for Testable::bool_type types which trigger an error. Easier to do with the CRTP form of the safe bool idiom since those operators become templates and thus can have an erroneous body.
Example:
template <typename T>
class safe_bool_concept
{
// Implementation detail of safe bool
protected:
~safe_bool_concept() {}
public:
operator safe_bool() const
{
return static_cast<const T*>(this)->is_null() ? ...;
}
};
struct Foo : safe_bool_concept<Foo>
{
...
private:
friend class safe_bool_concept<Foo>;
bool is_null() const { ... }
};
then you can do (do the same with !=):
template <typename T>
void operator==(const safe_bool_concept<T>& x, const safe_bool_concept<T>&)
{
x.some_private_member(); // invalid, but won't be generated
// unless safe_bool classes are compared
}
This means that the safe bool idiom should be implemented via CRTP if you want to forbid comparisons. Comparisons to zero will still work however.
If you go the non-member function route, you'll have to provide <, >, <= and >= too.
Related
I read few questions here on SO about this topic which seems yet confusing to me. I've just begun to learn C++ and I haven't studied templates yet or operator overloading and such.
Now is there a simple way to overload
class My {
public:
int get(int);
char get(int);
}
without templates or strange behavior? or should I just
class My {
public:
int get_int(int);
char get_char(int);
}
?
No there isn't. You can't overload methods based on return type.
Overload resolution takes into account the function signature. A function signature is made up of:
function name
cv-qualifiers
parameter types
And here's the quote:
1.3.11 signature
the information about a function that participates in overload
resolution (13.3): its parameter-type-list (8.3.5) and, if the
function is a class member, the cv-qualifiers (if any) on the function
itself and the class in which the member function is declared. [...]
Options:
1) change the method name:
class My {
public:
int getInt(int);
char getChar(int);
};
2) out parameter:
class My {
public:
void get(int, int&);
void get(int, char&);
}
3) templates... overkill in this case.
It's possible, but I'm not sure that it's a technique I'd recommend for
beginners. As in other cases, when you want the choice of functions to
depend on how the return value is used, you use a proxy; first define
functions like getChar and getInt, then a generic get() which
returns a Proxy like this:
class Proxy
{
My const* myOwner;
public:
Proxy( My const* owner ) : myOwner( owner ) {}
operator int() const
{
return myOwner->getInt();
}
operator char() const
{
return myOwner->getChar();
}
};
Extend it to as many types as you need.
As stated before, templates are overkill in this case, but it is still an option worth mentioning.
class My {
public:
template<typename T> T get(int);
};
template<> int My::get<int>(int);
template<> char My::get<char>(int);
No, you can't overload by return type; only by parameter types, and const/volatile qualifiers.
One alternative would be to "return" using a reference argument:
void get(int, int&);
void get(int, char&);
although I would probably either use a template, or differently-named functions like your second example.
Resurrecting an old thread, but I can see that nobody mentioned overloading by ref-qualifiers. Ref-qualifiers are a language feature added in C++11 and I only recently stumbled upon it - it's not so widespread as e.g. cv-qualifiers. The main idea is to distinguish between the two cases: when the member function is called on an rvalue object, and when is called on an lvalue object. You can basically write something like this (I am slightly modifying OP's code):
#include <stdio.h>
class My {
public:
int get(int) & { // notice &
printf("returning int..\n");
return 42;
}
char get(int) && { // notice &&
printf("returning char..\n");
return 'x';
};
};
int main() {
My oh_my;
oh_my.get(13); // 'oh_my' is an lvalue
My().get(13); // 'My()' is a temporary, i.e. an rvalue
}
This code will produce the following output:
returning int..
returning char..
Of course, as is the case with cv-qualifiers, both function could have returned the same type and overloading would still be successful.
You can think this way:
You have:
int get(int);
char get(int);
And, it is not mandatory to collect the return value of the function while invoking.
Now, You invoke
get(10); -> there is an ambiguity here which function to invoke.
So, No meaning if overloading is allowed based on the return type.
While most of the other comments on this problem are technically correct, you can effectively overload the return value if you combine it with overloading input parameter. For example:
class My {
public:
int get(int);
char get(unsigned int);
};
DEMO:
#include <stdio.h>
class My {
public:
int get( int x) { return 'I'; };
char get(unsinged int x) { return 'C'; };
};
int main() {
int i;
My test;
printf( "%c\n", test.get( i) );
printf( "%c\n", test.get((unsigned int) i) );
}
The resulting out of this is:
I
C
There is no way to overload by return type in C++. Without using templates, using get_int and get_char will be the best you can do.
You can't overload methods based on return types. Your best bet is to create two functions with slightly different syntax, such as in your second code snippet.
you can't overload a function based on the return type of the function.
you can overlead based on the type and number of arguments that this function takes.
I used James Kanze's answer using a proxy:
https://stackoverflow.com/a/9569120/262458
I wanted to avoid using lots of ugly static_casts on a void*, so I did this:
#include <SDL_joystick.h>
#include <SDL_gamecontroller.h>
struct JoyDev {
private:
union {
SDL_GameController* dev_gc = nullptr;
SDL_Joystick* dev_js;
};
public:
operator SDL_GameController*&() { return dev_gc; }
operator SDL_Joystick*&() { return dev_js; }
SDL_GameController*& operator=(SDL_GameController* p) { dev_gc = p; return dev_gc; }
SDL_Joystick*& operator=(SDL_Joystick* p) { dev_js = p; return dev_js; }
};
struct JoyState {
public:
JoyDev dev;
};
int main(int argc, char** argv)
{
JoyState js;
js.dev = SDL_JoystickOpen(0);
js.dev = SDL_GameControllerOpen(0);
SDL_GameControllerRumble(js.dev, 0xFFFF, 0xFFFF, 300);
return 0;
}
Works perfectly!
Here
https://youtu.be/dTeKf5Oek2c?t=2939
Stephen T. Lavavej says in a talk that const auto && is not useful.
Isn't the following a valid use case?
NonMovableNonCopyable create () {
// ...
return {};
}
const auto && obj = create ();
Concrete application: In XLL code, MS Excel generally does not like its xlopers to be copied or moved which it returns, since after copying or moving it will not be able to correctly free them.
Instead of
const auto && obj = create ();
... write just
const auto object = create();
... or
const auto object{ create() };
The = relies on the compiler eliding the copy constructor call, but I don't know about any extant compiler that fails to do that.
The clarity gained is IMO much more important than the guarantee offered by the reference (and if using reference, do use an ordinary & reference). Namely, one avoids having a maintenance programmer wasting time on trying to understand the rationale for the reference. If the type was explicitly specified it could be a case of polymorphic reference, Petru Marginean's trick, but with auto that's out of the question, and so the maintenance programmers are left scratching their heads, for some period of paid time.
On the other hand, const T&& can be useful for function overloading as an argument type to catch the case of a temporary as argument, in the same way as && qualifier for member function was considered sufficiently useful to be adopted in the standard. For example, even though I do not recommend this, if a pointer to the actual argument is stored for later use, then presumably one doesn't want to store a pointer to a temporary, which will end up as a dangling pointer:
struct Expr{ virtual ~Expr(){} };
struct Sum_expr: Expr
{
const Expr* a_;
const Expr* b_;
Sum_expr( Expr const& a,Expr const& b ): a_( &a ), b_( &b ) {}
template< class A >
Sum_expr( A&&, Expr const&& b ) = delete;
template< class B >
Sum_expr( Expr const&& a, B&& ) = delete;
};
auto main()
-> int
{
Expr a;
Expr b;
Sum_expr sum{ a, b };
Sum_expr sum2{ a, Expr() }; //! Nope, won't compile.
}
Note: Here A&& and B&& support both rvalue and lvalue actual arguments, i.e. they're not necessarily rvalue references, because they're universal references.
But instead of overloading and differentiating the cases I think I'd make that formal argument a pointer, even if a pointer technically can be a nullpointer, because as I see it, with what I'm accustomed to, it communicates the intent more clearly.
Sum_expr( Expr const* a, Expr const* b );
Const T && is very useful if T has a mutable field. A common example is a bool m_movedFrom that's initialized to false and gets set to true when moved from. This allows the rest of your object - resource handle, for example - to remain const.
class Resource // use this as a base class of const correct classes
{
private:
mutable bool m_movedFrom;
protected:
Resource()
: m_movedFrom(false)
{
}
Resource(const Resource&& other)
: m_movedFrom(false)
{
other.m_movedFrom = true;
}
bool isOwning() const // call from descendant's destructor
{
return m_movedFrom;
}
};
EDIT: a more complicated example explaining when the object is itself const, but a global state is not (not claiming this is the good way to solve this, it's for illustrational purposes only):
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
typedef std::string object_type;
typedef std::string seek_type;
class GoalSeeker
{
private:
static std::vector<const GoalSeeker*> s_store;
const std::vector<const GoalSeeker*>::iterator m_iter;
const object_type m_data;
public:
GoalSeeker( const object_type& data )
: m_iter( s_store.insert( s_store.end(), this ) ), m_data(data)
{
}
GoalSeeker( const GoalSeeker& ) = delete;
GoalSeeker( const GoalSeeker&& other )
: m_iter( other.m_iter ), m_data( other.m_data )
{
*m_iter = this;
}
~GoalSeeker()
{
if( *m_iter == this )
{
// cleanup m_data
}
}
static bool seek( const seek_type& needle )
{
return std::find_if(s_store.begin(), s_store.end(),
[&needle](const GoalSeeker* haystack)
{
return haystack->m_data.find(needle) != std::string::npos;
}) != s_store.end();
}
};
std::vector<const GoalSeeker*> GoalSeeker::s_store = {};
GoalSeeker fn()
{
return GoalSeeker("def");
}
int main() {
GoalSeeker a( "abc" );
GoalSeeker b( "cde" );
GoalSeeker s( (const GoalSeeker&&) fn() );
std::cout << GoalSeeker::seek( "de" ) << " " << GoalSeeker::seek( "fff" );
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Elegant solution to duplicate, const and non-const, getters?
Say I have a c++ class with a memberfunction which is overloaded for const, like this:
Type* DoSomething();
const Type* DoSomething() const;
If this is a larger, more complex member, how does one prevent having to write the same code twice ? Can't call any non-const functions from the const one. And calling the const version from the non-const one results in a const pointer wich has to be cast to non-const (wich smells a bit imo).
You can delegate to a template static member function, as in:
class Widget
{
Type member;
template<typename Result, typename T>
static Result DoSomethingImpl(T This)
{
// all the complexity sits here, calculating offsets into an array, etc
return &This->member;
}
public:
Type* DoSomething() { return DoSomethingImpl<Type*>(this); }
const Type* DoSomething() const { return DoSomethingImpl<const Type*>(this); }
};
In C++11, you can even get rid of the non-inferred template argument, with:
static auto DoSomethingImpl(T This) -> decltype(This->member)
You did it once, and to do it second time with a const attribute on the class, you can use const_cast:
class Foo
{
Type* DoSomething()
{
// Lots of stuff
}
const Type* DoSomething() const
{
return const_cast<Foo*>(this)->DoSomething();
}
}
Use the template method pattern to extract the common code from them. Eg.
inline const T* prev(size_t i) const
{
return &FBuffer[ AdjustIndex(i) ];
}
inline T* prev(size_t i)
{
return &FBuffer[ AdjustIndex(i) ];
}
inline size_t AdjustIndex( size_t i ) const
{
return Math::ModInt( static_cast<int>( FHead ) - 1 - i, static_cast<int>( FBuffer.size() ) );
}
This technique can be applied in many cases (but not all of them, i.e. if the behavior differs significantly).
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.