D opEquals() and opCast() give me a Segmentation Fault - d

I am trying to write a library of types representing a Global Trade Identification Number (GTIN) in the D Programming Language. There are four kinds of GTIN's, each named after the length of the number itself: GTIN8, GTIN12, GTIN13, and GTIN14. Each one of these is modeled as a class inheriting from an abstract GTIN class.
In the abstract GTIN class, I am overriding the opEquals operator to compare two GTINs of any kind. Since all of the smaller GTINs can be mapped to a broader GTIN14, each GTIN in the comparison gets cast to a GTIN14 first, then compared.
This all works fine until I compare one or more GTIN13s (or presumably, a smaller GTIN type as well), in which case, I get a segmentation fault.
It all begins with this unit test:
GTIN13 gtin1 = new GTIN13("123456789012");
GTIN13 gtin2 = new GTIN13("123456789012");
assert(gtin1 == gtin2);
The operator opEquals() has a signature of Object.opEquals(Object o), and changing the signature to anything else does not override ==. In my case, this becomes a call to gtin1.opEquals(cast(Object) gtin2). My opEquals override looks like this (subtracting the accumulated commented-out code and debug statements):
public override #trusted
bool opEquals(Object other)
{
GTIN14 a = cast(GTIN14) this;
GTIN14 b = cast(GTIN14) other;
for (int i; i < a.digits.length; i++)
{
if (a.digits[i] != b.digits[i]) return false;
}
return true;
}
As you can see, each GTIN is cast to a GTIN14 at the start of the function; however, other is first cast to an Object.
public
GTIN14 opCast(GTIN14)()
{
string currentGTINString = this.toString()[0 .. $-1];
while (currentGTINString.length < 13)
currentGTINString = ('0' ~ currentGTINString);
return new GTIN14(currentGTINString);
}
Further, my friend writeln() tells me that after the line GTIN14 b = cast(GTIN14) other; is executed, b is null. (It is not null before that line.)
So, in summary, the problem seems to be that casting a GTIN of any kind other than GTIN14 to an Object, then back to GTIN14 somehow deletes the object altogether. Is this a bug? Is this a problem with my code? Is there a workaround that does not compromise code quality?
I will appreciate any help I can get.

All right, I have several comments from your pastebin.
public abstract
class GlobalTradeItemNumber
{
// this could prolly just return _digits.length too.
public abstract #property
size_t length();
My general comment here is your code could be a bit simplified by making the length be borrowed from the array.... or you could also do something like a templated class with the length as a parameter.
I'll come back to that later though, first, let's fix your code. Moving on in the class:
public
/*
Note #1:
OK, this line is wrong:
//GTIN14 opCast(GTIN14)()
It should probably be:
*/
GTIN14 opCast(T : GTIN14)()
{
string currentGTINString = this.toString()[0 .. $-1];
while (currentGTINString.length < 13)
currentGTINString = ('0' ~ currentGTINString);
return new GTIN14(currentGTINString);
}
// we also need one for converting to the other sizes
// this could also be done with metaprogramming
GTIN13 opCast(T : GTIN13)()
{
string currentGTINString = this.toString()[0 .. $-1];
while (currentGTINString.length < 12)
currentGTINString = ('0' ~ currentGTINString);
return new GTIN13(currentGTINString);
}
The reason that line is wrong is that it actually defines a local template argument called GTIN14 which could be anything, and shadows the outer name!
So, my change here makes a new name T, which is then specialized to only match on the GTIN14 name from outside. See: http://dlang.org/spec/template.html#parameters_specialization
But then, it only applies to GTIN14, so I also added a second function that goes GTIN13 too.
If you were using a templated class, the specialization could also extract the length and you'd have one function that does them all. Or, if length as a compile-time constant (an enum) in each child class, you could pull it from there too.
Regardless, fixing your current code can be done with just the specialization syntax (T : class_name) and adding functions for the other subclasses too.
public
ulong toNumber()
{
ulong result;
// a note here: I would probably just have
// int exponent = 1;
// then exponent *= 10; in each loop instead of pow each time.
for (size_t i = this.length-1; i > 0; i--)
{
result += (this._digits[i] * (10^^(this._digits.length-i)));
}
return result;
}
Well, not much to say there, your code works, I would just write it a bit differently. The accumulator variable pattern would optimize it a wee bit. Of course, not really important here, just something to keep in mind.
/*
Note #2: this is where things get broken
*/
public override #trusted
bool opEquals(Object other)
{
/*
these are actually two different kinds of casts
GTIN14 b = cast(GTIN14) other; // does a generic dynamic cast!
GTIN14 a = cast(GTIN14) this; // actually calls the opCast
*/
GTIN obj = cast(GTIN) other;
if(obj is null) // which might return null because Object is not necessarily an instance of your class
return false; // definitely not a match
GTIN14 b = cast(GTIN14) obj;
GTIN14 a = cast(GTIN14) this;
for (int i; i < a.digits.length; i++)
{
if (a.digits[i] != b.digits[i]) return false;
}
return true;
}
public override #trusted
int opCmp(Object other)
{
// GTIN14 that = cast(GTIN14) other; // a generic dynamic cast!
GTIN obj = cast(GTIN) other;
if(obj is null) // which might return null because Object is not necessarily an instance of your class
return -1; // so return something indicating not a match
GTIN14 that = cast(GTIN14) obj; // now you can use your custom cast
const ulong thisNumber = this.toNumber();
const ulong thatNumber = that.toNumber();
if (thisNumber == thatNumber) return 0;
return ((thisNumber / 10u) > (thatNumber / 10u) ? 1 : -1);
}
The other opCmps in the child classes make the same mistake and can be fixed the same way.
But this is the main thing causing your trouble - the same cast syntax actually does two different things!
See, the static type of other is the generic base class Object, so it isn't aware of your custom cast function yet. (opCast, being a template, cannot be virtual and thus is not override like other functions that modify the behavior of generic function)
Instead, it does a generic dynamic_cast (that's the C++ name, D just calls them all cast, but it is the same concept so you can read more about it by searching for the C++ term if you like). It tries to convert the base class/interface back to the subclass using a runtime type tag. If it is indeed an instance of that class (or one of its own subclasses), the cast succeeds and you get the reference. Otherwise, it returns null. This is the cause of your segfault.
On the other hand, the cast(xxx) this already knows it is an instance of GTIN (or one of its subclasses), so it is able to use your custom opCast conversion. So, your a variable called the right function and got populated correctly, but your b variable would be null... unless you happened to actually be comparing two GTIN14 instances. Then the dynamic cast would succeed, but not for the other classes.
So, the fix is to first cast that generic Object other back to your GTIN base class, check for null (this would happen if a user wrote like GTIN14 a = new GTIN14("xxx"); Object b = new Object(); assert(a == b); /* uh oh, b is an Object, so it should just return null */.
BTW, when comparing against null, you should usually use a is null instead of a == b because if a itself is null, it will crash when trying to access the virtual opEquals function!
Anyway, after you cast it back to GTIN, then you can cast again and invoke your conversion function.
Alternatively, you might also use a different named function like perhaps toGTIN14 in the base class that generically does the conversion, and you just call that from each instance of the base class and convert them that way instead of using the cast keyword. That'd actually be the way I'd write it - it is my preference, but both ways work.
Both opEquals and opCmp, from any classes where they are implemented, need to follow this same pattern. In opEquals you can see I return false when it is null, since they obviously aren't equal if they can't even be converted to a common type!
But in opCmp, you don't want to return 0 since that means equal, but what to actually return is a mystery to me.... I just did -1 so all the other objects in that array would be sorted earlier but maybe you have a better idea. I don't know what's best.
Anyway yeah, doing those changes should fix your code.
Lastly, as a bonus, here's an implementation of the generic templated class:
alias GTIN14 = GlobalTradeItemNumberImpl!14;
alias GTIN13 = GlobalTradeItemNumberImpl!13;
public
class GlobalTradeItemNumberImpl(int size) : GlobalTradeItemNumber
{
public override #property
size_t length()
{
return size;
}
this(string digits)
{
super(digits);
}
}
If you've ever looked at some of Phobos' innards, you will see patterns similar to this in std.base64 and std.digest.
With that, all the functionality is actually in the base class now. You can rewrite the opCast as thus in the base class:
T opCast(T : GlobalTradeItemNumberImpl!N, int N)()
{
string currentGTINString = this.toString()[0 .. $-1];
while (currentGTINString.length < (N-1))
currentGTINString = ('0' ~ currentGTINString);
return new T(currentGTINString);
}
The specialization there uses the "pattern matching" described in form #7 of this: http://dlang.org/spec/expression.html#IsExpression to catch any random N, and extract what it is for use inside the function.
There's other optimizations we could do too if you're interested, like the use of the ~ operator, or it could even be changed from classes to struct using alias this to combine common functionality.. but I'll let you play with that if you want to :)

Related

Is there a way to make a function have different behavior if its return value will be used as an rvalue reference instead of an lvalue?

I have a routine that does some moderately expensive operations, and the client could consume the result as either a string, integer, or a number of other data types. I have a public data type that is a wrapper around an internal data type. My public class looks something like this:
class Result {
public:
static Result compute(/* args */) {
Result result;
result.fData = new ExpensiveInternalObject(/* args */);
return result;
}
// ... constructors, destructor, assignment operators ...
std::string toString() const { return fData->toString(); }
int32_t toInteger() const { return fData->toInteger(); }
double toDouble() const { return fData->toDouble(); }
private:
ExpensiveInternalObject* fData;
}
If you want the string, you can use it like this:
// Example A
std::string resultString = Result::compute(/*...*/).toString();
If you want more than one of the return types, you do it like this:
// Example B
Result result = Result::compute(/*...*/);
std::string resultString = result.toString();
int32_t resultInteger = result.toInteger();
Everything works.
However, I want to modify this class such that there is no need to allocate memory on the heap if the user needs only one of the result types. For example, I want Example A to essentially do the equivalent of,
auto result = ExpensiveInternalObject(/* args */);
std::string resultString = result.toString();
I've thought about structuring the code such that the args are saved into the instance of Result, make the ExpensiveInternalObject not be calculated until the terminal functions (toString/toInteger/toDouble), and overload the terminal functions with rvalue reference qualifiers, like this:
class Result {
// ...
std::string toString() const & {
if (fData == nullptr) {
const_cast<Result*>(this)->fData = new ExpensiveInternalObject(/*...*/);
}
return fData->toString();
}
std::string toString() && {
auto result = ExpensiveInternalObject(/*...*/);
return result.toString();
}
// ...
}
Although this avoids the heap allocation for the Example A call site, the problem with this approach is that you have to start thinking about thread safety issues. You'd probably want to make fData an std::atomic, which adds overhead to the Example B call site.
Another option would be to make two versions of compute() under different names, one for the Example A use case and one for the Example B use case, but this isn't very friendly to the user of the API, because now they have to study which version of the method to use, and they will get poor performance if they choose the wrong one.
I can't make ExpensiveInternalObject a value field inside Result (as opposed to a pointer) because doing so would require exposing too many internals in the public header file.
Is there a way to make the first function, compute(), know whether its return value is going to become an rvalue reference or whether it is going to become an lvalue, and have different behavior for each case?
You can achieve the syntax you asked for using a kind of proxy object.
Instead of a Result, Result::compute could return an object that represents a promise of a Result. This Promise object could have a conversion operator that implicitly converts to a Result so that "Example B" still works as before. But the promise could also have its own toString(), toInteger(), ... member functions for "Example A":
class Result {
public:
class Promise {
private:
// args
public:
std::string toString() const {
auto result = ExpensiveInternalObject(/* args */);
return result.toString();
}
operator Result() {
Result result;
result.fData = new ExpensiveInternalObject(/* args */);
return result;
}
};
// ...
};
Live demo.
This approach has its downsides though. For example, what if, instead you wrote:
auto result = Result::compute(/*...*/);
std::string resultString = result.toString();
int32_t resultInteger = result.toInteger();
result is now not of Result type but actually a Result::Promise and you end up computing ExpensiveInternalObject twice! You can at least make this to fail to compile by adding an rvalue reference qualifier to the toString(), toInteger(), ... member functions on Result::Promise but it is not ideal.
Considering you can't overload a function by its return type, and you wanted to avoid making two different versions of compute(), the only thing I can think of is setting a flag in the copy constructor of Result. This could work with your particular example, but not in general. For example, it won't work if you're taking a reference, which you can't disallow.

LevelDB --- Code in C++

The below given code is taken from LevelDB. I am giving two blocks of code for better understanding. I am unable to understand what is happening.
ThreadState is a structure and I have written here to make it easy for the reader.
struct ThreadState {
int tid; // 0..n-1 when running in n threads
Random rand; // Has different seeds for different threads
Stats stats;
SharedState* shared;
ThreadState(int index)
: tid(index),
rand(1000 + index) {
}
};
Is the marked code below an object instantiation of class Benchmark? What is happening in the marked code below?
void Run() {
PrintHeader();
Open();
const char* benchmarks = FLAGS_benchmarks;
while (benchmarks != NULL) {
{
//code ommitted
}
// Reset parameters that may be overriddden bwlow
***void (Benchmark::*method)(ThreadState*) = NULL;*** // What does this code line mean? // Benchmark is a class.
bool fresh_db = false;
int num_threads = FLAGS_threads;
if (name == Slice("fillseq")) {
fresh_db = true;
method = &Benchmark::WriteSeq;
}
If required, I can give detailed implementation of Benchmark as well.
Thanks a lot for the help!
void (Benchmark::*method)(ThreadState*) = NULL;
// What does this code line mean?
// Benchmark is a class.
The above is a pointer to a member function. Since member functions are not like regular functions (they can only be called on a valid object), you cannot take their address it the same way you would for a free function.
Therefore the above syntax is introduced. It is similar to a regular function pointer except the class specifier Benchmark::. This is essentially the type of the implicit this pointer.
In your case, method is a pointer to a member function that takes ThreadState* as a parameter, and has a void return type. The reason for using it is most probably to simplify the call. First, and based on various parameters, a member function is chosen to be called, and its "address" stored in method. After all the checks are done, there is only a single call to the chosen function via the pointer to member.
Incidentally, &Benchmark::WriteSeq is how the code obtains the "address" of the member function WriteSeq. You must use the address-of operator on the qualified function name.

C++ method returns pointer to abstract class, need to use a method from the subclass

so I'm writing a compiler in C++. Currently on the scanner portion.
The method declaration inside the scanner is
Token * Scanner::next_token()
{
string * test = new string("Test");
IdToken * testToken = new IdToken(test);
return testToken;
}
The IdToken class has a method get_attribute() that returns the value of the private variable attr (which in this case is a string, the one passed in on creation). Token (the abstract class) does not have this method.
Inside the main of my testing I have this:
IdToken * testToken = testScanner->next_token();
But g++ doesn't like that, and says that it's an invalid conversion from Token* to IdToken*.
I need to turn the token returned by the method into an IdToken in order to get the attribute, since when I try to directly call get_attribute() on the token returned it tells me that Token::get_attribute() does not exist.
Not sure entirely how to go about fixing this since my knowledge of C++ inheritance and such is struggling. I did all the research I could but I couldn't find anything that I both understood and solved my problem.
Here is Scanner.cc
Scanner::Scanner (char * filename)
{
buf = new Buffer(filename);
}
//Destroy new things
Scanner::~Scanner()
{
delete buf;
}
//The huge DFA turned into code
Token * Scanner::next_token()
{
string * test = new string("Test");
IdToken * testToken = new IdToken(test);
return testToken;
}
And here is IdToken.cc
IdToken::IdToken() : Token()
{
set_token_type (TOKEN_ID);
attribute = new string("UNINITIALIZED IDENTIFIER ATTRIBUTE");
}
IdToken::IdToken (string *attr) : Token()
{
set_token_type (TOKEN_ID);
attribute = new string(*attr);
}
IdToken::~IdToken()
{ if (attribute != NULL) {
delete attribute;
}
}
string *IdToken::get_attribute() const
{
string *attr = new string(*attribute);
return attr;
}
void IdToken::set_attribute(string *attr)
{
if (attribute != NULL) {
delete attribute;
}
attribute = new string (*attr);
}
string *IdToken::to_string()
{
string *attribute_name = new string ("ID:" + *attribute);
return attribute_name;
}
And lastly token.cc
#include "token.h"
Token::Token()
{
type = TOKEN_NO_TYPE;
}
Token::~Token()
{}
void Token::set_token_type (token_type_type type)
{
this->type = type;
}
token_type_type Token::get_token_type() const
{
return type;
}
It's not nearly done, I just need help with figuring out how to access get_attribute.
Couple of options:
Create a virtual member function in Token.
virtual std::string get_attribute() const = 0;
Implement appropriately for the sub-classes of Token. Use it as:
Token * testToken = testScanner->next_token();
std::string attr = testToken->get_attribute();
Use dynamic_cast to get an IdToken* from a Token*. If the cast is successful, call get_attribute(). on the IdToken*.
Token * testToken = testScanner->next_token();
IdToken * testIdToken = dynamic_cast<IdToken*>(testToken);
if ( testIdToken )
{
std::string attr = testIdToken->get_attribute();
}
You can use a dynamic_cast
struct Token {
virtual ~Token() {}
};
struct IdToken : public Token {
int getAttribute() {return 1;}
};
int main(int argc, char** argv} {
Token* token = new IdToken();
dynamic_cast<IdToken*>(token)->getAttribute();
delete token;
}
Unfortunately, dynamic_cast tends to be rather slow and you would probably want to avoid frequent calls to it. It is safe, however. It returns a nullptr on failure. You could also use reinterpret_cast, which is faster, but isn't safe.
I personally wouldn't make a class hierarchy for the tokens. There's a relatively small set of attributes and parameters, and you could, potentially, use a union to store them, if you really have to.
But if you MUST, then use dynamic_cast to call your get_attribute:
Token* token = testScanner->next_token()
IdToken *idToken = dynamic_cast<IdToken*>(token);
if(idToken)
{
idToken->get_attribute();
}
Note that you do need the if, or your program will crash if the token you got wasn't an IdToken [or derived from an IdToken].
Oh, and dynamic_cast is not a trivial operation that takes no time at all. So avoiding it in preference for a base-class virtual function is nearly always better. My compiler uses a couple of dozen llvm::dyn_cast, for the AST that comes out of the parser, because doing a fully generic AST class that can cope with all the special cases of variable expressions, for-loops and function declarations in the same class would make a monster of a class with a few dozen virtual functions, most of which would require a single implementation for a single derived class, but a "null" value for most others - and most of the time I'd need to know what class it actually is anyway...
Here's my Token class - I'm sure there are faults there too, I'm not a compiler expert, this is my third language I've worked on, and the first one to actually compile to machine code, and I'm cheating by using llvm as the backend.
Don't do string *something = new string; use an empty or "unknown" string to mean "not yet set"
Also don't use if (pointer) delete pointer; - delete works just fine on pointers that are NULL - the redundant if is probably not removed by the compiler, since in a vanishingly small number of cases, the extra overhead of calling delete is worth saving - but not in a destructor. If you have an additional if (pointer) everywhere in a large project, it soon adds up to several thousand bytes of extra code - if the destructor then happens to be inlined, it's multiplied by the number of inlines it has, which could be quite a lot of useless code in your project. Compiler code tends to get large enough without useless bloat.

dereferencing this causes Segmentation fault

I have the following functions
LinearScheme::LinearScheme() {
cout << " empty constructor" << endl;
}
void LinearScheme::init(
int tableId,
std::string &basePath,
std::vector<size_t> &colElemSizes,
TupleDescMap &tupleDescMap,
size_t defaultMaxFragmentSize,
int numCols,
BoundBases &bounds,
std::vector<int> &colsPartitioned )
{
// This linear scheme ignores bounds
// it could be improved to use colsPartitioned for ordering (TODO)
cout << "init Linear Scheme " << endl;
*this = LinearScheme(); //SEGFAULTS HERE
cout << "after cons here?" << endl;
// init private fields
this->tableId_ = tableId;
this->basePath_ = basePath;
this->colElemSizes_ = colElemSizes;
this->numCols_ = numCols;
this->tupleDescMap_ = tupleDescMap;
this->numFragments_ = 0;
this->defaultMaxFragmentSize_ = defaultMaxFragmentSize;
// fragmentSizesFilename_ init
fragmentSizesFilename_ = basePath_ + boost::lexical_cast <string>(tableId_)
+ "_cs";
struct stat st;
// open existing file if exists. Create new otherwise.
if (stat(fragmentSizesFilename_.c_str(), &st) == 0) // file existed
openExisting();
else
createNew();
}
The reason I am initializing in init rather than constructor is because LinearScheme extends a PartitionScheme (super class with virtual methods) class and another class does that where the constructor is used recursively.
I have a QuadTree class which does the same initialization because each QuadTree constructor is applied recursively. *this = QuadTree(bounds, maxSize) line in the init function of QuadTree class works just fine.
however, this line in the other subclass (LinearScheme) *this = LinearScheme() cause a Seg fault.
Any ideas why this might happen?
EDIT
Also replacing the line:
*this = LinearScheme()
with this:
*this;
or removing it overall gets rid of the Seg Fault ... why?
Sounds like incorrect factory method / builder / deferred construction usage. For many of these object creation patterns function that constructs your objects should be a static method because there doesn't yet exist an instance to manipulate. In others you potentially manipulate an already constructed instance. In either case if you are actually constructing the object of the class type within the function you should be using new and eventually returning it.
If you are instead going for a helper method to assist with initialization then you simply shouldn't be constructing the object within the method itself, and you should just be initializing parts of it within your helper.
A factory pattern example:
LinearScheme* LinearScheme::create(...all_your_args....) {
/* construct the thing we are building only if it
* pass any arguments into him that he can handle directly if you'd like
*/
LinearScheme *out = new LinearScheme(...);
/* do whatever else you have to do */
....
return out;
}
or this helper of sorts that you seem to want
/* this time let's just do 'init' on your object */
void LinearScheme::init(....args....) {
/* possibly check if init has been done already */
if ( this->init ) return;
/* proceed to do your initialization stuff
* but don't construct the 'this' instance since it should already exist
*/
this->init = true; //so we don't init again if you don't need multiple init's
}
Alternatively you can consider the delegate constructor methods in C++11 alex mentions.
However neither of these really strikes me as being the actual problem here.
It's not working because either you probably don't even have a valid *this to deference. This could be because of your usage, or it could be because one failed to create potentially because of infinite recursion.
Here's a wikipedia link on the pattern: http://en.wikipedia.org/wiki/Factory_method_pattern
Given what you have said about having to keep passing a dozen arguments around both to parent classes and for your recursive construction, one suggestion you could consider is making a small config struct that you pass along by reference instead of all the discrete parameters. That way you don't have to keep adjusting every signature along the way each time you add / remove another parameter.
The other idea is to seperate entirely the construction of one of your objects from the responsibility of knowing how, where, and when they should be contructed and inserted into your hierarchy. Hard to say without understanding how you will actually be using LinearSchme and what the interface is.
"...in the other subclass (LinearScheme) *this = LinearScheme()"
"The LinearScheme constructor is empty: LinearScheme::LinearScheme()"
if *this is a subclass of LinearMethod, LinearMethod's constructor should already have been called and this line is useless. Besides it calls assignment operator - is it properly defined?
It is better to rely on built-in mechanism of constructing of objects. If you want to avoid code repetition, use C++11 delegating constructors feature. It was specially designed to eliminate "init" methods.
Although, "If there is an infinitely recursive cycle (e.g., constructor C1 delegates to another constructor C2, and C2 also delegates to C1), the behavior is undefined."
So it is up to you to avoid infinite recursion. In your QuadTree you can consider creating nullptr pointers to QuadTreeNode in constructor.

Can I make the ternary operator treat my class like a bool?

I've recently been doing a huge refactoring where I was changing a lot of my code to return booleans instead of an explicit return code. To aid this refactoring I decided to lean on the compiler where possible by getting it to tell me the places where my code needed to be changed. I did this by introducing the following class (see here for the lowdown on how this works):
///
/// Typesafe boolean class
///
class TypesafeBool
{
private:
bool m_bValue;
struct Bool_ {
int m_nValue;
};
typedef int Bool_::* bool_;
inline bool_ True() const { return &Bool_::m_nValue; }
inline bool_ False() const { return 0; }
public:
TypesafeBool( const bool bValue ) : m_bValue( bValue ){}
operator bool_() const { return m_bValue ? True() : False(); }
};
Now, instead of using a normal bool type as the return type, I used this class which meant that I couldn't compile something like this any more:
TypesafeBool SomeFunction();
long result = SomeFunction(); // error
Great: it has made the refactoring manageable on a huge codebase by letting the compiler do a lot of the hard work for me. So now I've finished my refactoring and I'd quite like to keep this class hanging around and carry on using it since it affords us an extra level of safety that the built-in bool type doesn't.
There is however one "problem" which is preventing me from doing this. At the moment we make heavy use of the ternary operator in our code, and the problem is that it is not compatible with this new class without explicit casts:
TypesafeBool result = ( 1 == 2 ? SomeFunction() : false ); // error: different types used
TypesafeBool result = ( 1 == 2 ? SomeFunction() : (TypesafeBool)false );
If I could "solve" this issue so that I could use my class in a seamless manner I would probably carry on using it throughout the codebase. Does anyone know of a solution to this issue? Or is it just impossible to do what I want?
In the context of the conditional operator, the type of the expression is the common type of the last two operands. The complete rules to determine this common type are a bit complex, but your case happens to be trivial: if one of the two possible return values is a class type, the other value must have the same class and the common type is obviously also that class.
That means that if one of the operands is a TypesafeBool, then the other must be as well.
Now the problem you're really trying to solve has been solved before. The trick is not providing a class; instead use a typedef. See for instance safe bool.
class CCastableToBool
{
public:
// ...
operator bool() const
{
//...
{
return true;
}
//...
return false;
}
private:
// ...
};
but beware, in C++ it is considered really dangerous to have a class that can be casted to bool. You are warned :-)
you can read this there, SafeBool
You should explicitely call TypesafeBool::True() in all your ternary tests.
TypesafeBool result = ( 1 == 2 ? SomeFunction().True() : false );
I don't know about a seamless manner, the ternary operator has some restrictions on its use...
However, why don't you define two constants ?
TypesafeBool const True = TypesafeBool(true);
TypesafeBool const False = TypesafeBool(false);
And then:
TypesafeBool result = ( 1 == 2 ? SomeFunction() : False );
Of course, it's a bit unorthodox since I play on the capitalization to avoid reusing a reserved word :)
Is it a possibility to make the constructor of TypesafeBool explicit? Of course, now the usage has to be
TypesafeBool result( 1 == 2 ? b : false );
Could you use an assignment operator that takes in a bool as the external argument, as well as one that takes a TypesafeBool? It might be something to try out...
Nice try, but if your code base is large, you are probably better off using a static checker such as PC-Lint to look for implicit bool<->int conversions instead.