This is very subjective question. I'm trying to write a logic "set null or use index argument". And I came up with the idea of additional bool argument or using negative index argument for set null condition. I wonder which one would be better.
For example, if there is a class member function as below,
bool DoSomething(bool bSetNull, unsigned int unIndex)
{
bool bReturn = false;
if (bSetNull)
{
m_pObject = nullptr;
}
else
{
m_pObject = m_pArr[unIndex]; // m_pArr could be replaced by something like m_map.find(unIndex)
bReturn = true;
}
return bReturn;
}
vs.
bool DoSomething(int nIndex)
{
bool bReturn = false;
if (nIndex < 0)
{
m_pObject = nullptr;
}
else
{
m_pObject = m_pArr[unIndex]; // m_pArr could be replaced by something like m_map.find(unIndex)
bReturn = true;
}
return bReturn;
}
Actually, the former is bothering due to additional bool argument and the latter is bothering due to use of signed type of index argument.
Please give me advice if there is better option.
In standard C there are some examples of the signed int usage like int snprintf return the length or a negative error code.
Because of the long history of C this is not a qualitative argument, but this option will not come as surprise.
However better use an std::optional field (for instance) and two functions with and without index. That is not tweaking semantics: the meaning of things.
Related
Let's assume that, we have a C API exposed by a C++ library where the C client queries a value by passing a void pointer and a key.
bool GetValue(const char* key, void* val) {
if(val != NULL) {
// find the value using the key with some logic of library
// lets assume found value is a int
int foundValue = 34;
*(int*)val = foundValue;
return true; // or false if key not found
}
return false;
}
The C client and the C++ library developers have an agreement about the size of values associated with keys.
Let's assume the C++ library only has int and long long int, and the C client also knows it.
So the C client is expected to behave as follows when the value associated with "some_key" is an int:
int valueHolder;
if(GetValue("some_key",&valueHolder)) {
// do something with valueHolder
}
But the C client can cause stack memory corruption by providing pointer which points to less space. For example, if the C client provides a pointer which points to an unsigned char and the value written by the C++ library is int, stack memory corruption can happen.
So the C client should take proper action to avoid such a situation. My question is, how the C++ library can handle such memory corruption/crash situation and be robust to crash or memory corruption? (a small note: a template or function overload is not an option for me because C++ library can not expose such feature to a C client).
Simply you have to design API in such way that type of the value is clear.
So for example:
bool GetIntValue(const char* key, int* val) {
if(val != NULL && IsIntValue(key)) {
// find the value using the key with some logic of library
// lets assume found value is a int
int foundValue = 34;
val = foundValue;
return true;
}
return false;
}
bool GetSizeValue(const char* key, size_t* val) {
if(val != NULL && IsSizeValue(key)) {
// find the value using the key with some logic of library
// lets assume found value is a int
size_t foundValue = 12;
val = foundValue;
return true;
}
return false;
}
...
Or other way:
enum Types {
Int,
Size,
....
};
struct Variant {
enum Types type;
union {
int integer;
size_t size;
....
};
};
bool GetVariantValue(const char* key, struct Variant* val) {
if(val != NULL) {
...
*val = MakeIntVariant(33);
return true;
}
return false;
}
Unfortunately it cannot be made robust, see this link:
Checking if a pointer is allocated memory or not
You can catch the crash however using something like
try {} catch (...) {}
but there is no guarantee it will crash, and in fact it is very likely to instead overwrite/corrupt adjacent memory.
I'm learning C++ with previous Java experience.I found the following example in the cplusplus.com :
int CDummy::isitme (CDummy& param)
{
if (¶m == this)
{
return true; //ampersand sign on left side??
}
else
{
return false;
}
}
My question is : Why does it return boolean false when I clearly declared the method as int ? It's never possible in Java.
The link of the example is : here.
While the question of why the function does what it does is best answered by the author of the function, it is easy to explain why C++ allows such function to compile without a problem.
In C++ bool is a fundamental integral type, so it can be freely converted to a number: true becomes 1, and false becomes zero.
This is just an instance of implicit conversion. In c++, 1 and true (also 0 and false) are the same thing(s).
You could also do something like
while (1)
//Infinite loop
or
bool b = false;
if (b == 0) {
//This is reached
}
else {
//This is not
}
I have researched my issue all over StackOverflow and multi-google links, and I am still confused. I figured the best thing for me is ask...
Im creating a simple command line calculator. Here is my code so far:
const std::string Calculator::SIN("sin");
const std::string Calculator::COS("cos");
const std::string Calculator::TAN("tan");
const std::string Calculator::LOG( "log" );
const std::string Calculator::LOG10( "log10" );
void Calculator::set_command( std::string cmd ) {
for(unsigned i = 0; i < cmd.length(); i++)
{
cmd[i] = tolower(cmd[i]);
}
command = cmd;
}
bool Calculator::is_legal_command() const {
switch(command)
{
case TAN:
case SIN:
case COS:
case LOG:
case LOG10:
return true;
break;
default:
return false;
break;
}
}
the error i get is:
Calculator.cpp: In member function 'bool Calculator::is_trig_command() const':
Calculator.cpp: error: switch quantity not an integer
Calculator.cpp: error: 'Calculator::TAN' cannot appear in a constant-expression
Calculator.cpp: error: 'Calculator::SIN' cannot appear in a constant-expression
Calculator.cpp: error: 'Calculator::COS' cannot appear in a constant-expression
The mighty internet, it says strings are allowed to be used in switch statements.
Thanks everyone, I appreciate your help.
In switch, the expression must be of "an integral type or of a class type for which there is an unambiguous conversion to integral type" (quoting VS2008 docs).
A string class doesn't have "unambiguous conversion to integral type", like a char does.
As a work-around:
Create a map<string, int> and switch on the value of the map: switch(command_map[command])
`
Do a set of if/else instead of switch. Much more annoying and hard to read, so I'd recommend the map route.
As an aside, an even better solution for really complicated logic like that is to improve the mapping solution to get rid of switch completely and instead go with a function lookup: std::map<std::string, functionPointerType>. It may not be needed for your specific case, but is MUCH faster for complicated very long look-up logic.
As others and the compiler commented, strings are not allowed with switch. I would just use if
bool Calculator::is_legal_command() const {
if(command == TAN) return true;
if(command == SIN) return true;
if(command == COS) return true;
if(command == LOG) return true;
if(command == LOG10) return true;
return false;
}
I don't think that's any more complicated, and it's about as fast as it could get. You could also use my switch macro, making it look like
bool Calculator::is_legal_command() const {
sswitch(command)
{
scase (TAN):
scase (SIN):
scase (COS):
scase (LOG):
scase (LOG10):
return true;
sdefault():
return false;
}
}
(having break after a return is dead code, and so should be avoided).
Strings cannot be used in switch statements in C++. You'll need to turn this into if/else if, like this:
if (command == "tan")
{
// ...
}
else if (command == "cos")
{
// ...
}
// ...
Not sure which mighty Internet you've been reading, but C++ doesn't allow strings in switch statements. (C# does, though.)
You need to convert your switch statement to a chain of if-else if-else statements that test equality.
Rather than a switch.
I would use a command pattern. Then use a std::map to map the function name to the command object.
Something like this:
#include <math.h>
#include <map>
#include <string>
#include <iostream>
class Function
{
public:
// Easy public API that just uses the normal function call symantics
double operator()(double value) { return this->doWork(value);}
virtual ~Function() {}
private:
// Virtual function where the work is done.
virtual double doWork(double value) = 0;
};
// A sin/cos function
class Sin: public Function { virtual double doWork(double value) { return sin(value); } };
class Cos: public Function { virtual double doWork(double value) { return cos(value); } };
// A class that holds all the functions.
// A function name is mapped to a function object.
class FuncMap
{
public:
FuncMap()
{
// Constructor sets up the map
functions["sin"] = &sinFunc;
functions["cos"] = &cosFunc;
}
Function* getFunction(std::string command) const
{
// Default result not found.
Function* result = NULL;
std::map<std::string, Function*>::const_iterator find;
// Look in the map to see if we find the value.
// If it exists then find will not point at end()
if ((find = functions.find(command)) != functions.end())
{
// Get the pointer to the function
result = find->second;
}
return result;
}
private:
Sin sinFunc;
Cos cosFunc;
std::map<std::string, Function*> functions;
};
// Declaring it globally for ease of use.
FuncMap functions;
int main()
{
// SImple example of usage.
Function* func = functions.getFunction("sin");
if (func == NULL)
{
std::cout << "No Function sin()\n";
exit(1);
}
std::cout << "Result: " << (*func)(12.34) << "\n";
}
The compiler error tells you everything you need to know. Only integral types may be compared in switch statements.
I'm not sure which "mighty internet" told you otherwise, but it was mighty wrong.
Strings cannot be used as constants in switch statements in c++. You can either use a map, a series of if's or you can move from representing your commands as strings to an enum. Parse from string to enum once, then use a switch like you do now. Note that your string parsing may require the same mechanism (map/if's), but depending on your use case using one approach over the other may improve readability. I'm not going to say anything on which approach is more readable.
I keep on receiving odd unexpected values for my bool testValue. I keep receiving random numbers as I believe it is trying to access another region of memory. I predict it is how my code is setup within my testNumber() function, but I am unsure of how to solve it. This is my logic.
I have set ok to true. Now I assign the memory address of ok to pOk.
void TextBox::lengthTest(bool *pOk, int length) {
bool ok;
if (length < MAX_LENGTH) {
ok = true;
pOk = &ok;
} else {
ok = false;
pOk = &ok;
}
}
bool lengthTestBool = lengthTest(*pOk, length);
cout << lengthTestBool <<;
output:
85
You have a fundamental misunderstanding of how one uses pointers to implement reference semantics. You want to change thing that is pointed to by the pointer:
*pOK = ok;
However, C++ actually supports references semantics natively through reference types, which may be preferable:
void testNumber(bool & OK, int n)
{
OK = true;
// ...
}
Even better, though, is to simply return a bool:
bool testNumber(int n) { /* ... */ }
if (testNumber(x)) //... etc.
I have a function in a C++ program returning a string.
On certain conditions, e.g. if the function encounters an error or so, I want to return a special value telling the caller that something has gone wrong.
I could basically just return an empty string "", but the function does need the empty string as normal return value.
How can I accomplish this?
Do I have do create a special data structure that for my function that holds a bool if the function was successfully run and a string containing the actual return value?
This sounds like a usecase for exceptions.
try {
std::string s = compute();
} catch(ComputeError &e) {
std::cerr << "gone wrong: " << e.what();
}
If you don't want to or can't use exceptions, you could change the function's interface
std::string result;
if(!compute(result)) {
std::cerr << "Error happened!\n";
}
Though most often, i've seen the return value is used for the actual result, and an error pointer is passed
bool b;
std::string s = compute(&b);
if(!b) {
std::cerr << "Error happened!\n";
}
This has the benefit that you can default the error argument pointer to 0 and code that can ignore the error (because it could live with an empty string return, for example, or if it knows in advance the input is valid) would not need to bother:
std::string compute(bool *ok = 0) {
// ... try to compute
// in case of errors...
if(ok) {
*ok = false;
return "";
}
// if it goes fine
if(ok) {
*ok = true;
}
return ...;
}
You can definitely return a pair, although it is klunky.
pair< string, bool > my_method(...) {
if (a) {
return make_pair(some_value, true);
} else {
return make_pair("", false); // error
}
}
pair< string, bool > result = my_method(...);
if (result.second) {
// success
} else {
// error
}
You can also pass either the bool or the string by reference,
bool my_method(string& s, ...) {
...
}
string s;
if (my_method(s, ...)) {
// success
} else {
// error
}
or:
string my_method(bool& ok, ...) {
ok = false; // default
...
}
bool ok;
s = my_method(ok, ...));
if (ok) {
// success
} else {
// error
}
You could try returning an auto_ptr to a string, but this will cost you an explicit new-ing of a string.
std::auto_ptr<std::string> Foo(int i)
{
if(i == 0) // Error!
return std::auto_ptr<std::string>(NULL);
else // Works.
return std::auto_ptr<std::string>(new string("Hello world!"));
}
If it's really something like an error, you should throw an exception. But by reading your question I guess it's not an "exceptional behaviour"?
If that's the case, you have several non-perfect solutions :
Return a structure with the string and a boolean that tells if the function failed (a simple std::pair<> could be enough).
Make your function modify a string parameter provided by reference and return a boolean telling if the function failed.
Make your function a functor/object that have a state. That state would be (at least) a boolean giving the failure or success of the last function call -- that would then be a function call.
3 is IMO bad design, while 2 and 1 are unperfect compromise.
It depends on how is your program organized.
You may return an additional boolean signifying if the function succeeded. You may return a structure containing boolean and string. You may return a special string (not necessarily empty) which should represent the failure. You may throw an exception. You may set a global flag indicating an error (though I would not recommend it).
There must be lot of other methods to express function failure, too.
The std::pair<> method is good. Another alternative is to have the caller pass the output string in as a non-const reference, and have the function return true or false depending on if an error was encountered or not.
bool Foo(int i, std::string& result)
{
bool ret = false; // no error
// do stuff...
result = "blahbalhbalh";
return ret;
}