I have an assignment where i was given c++ code that has multiple test functions, and i have to write the stri class with all the functions necesary for these tests to pass. I am having difficulty with one particular test about chain linking.
void Lab4Tests::testChainedSet() {
stri greet = "Hello";
assert(0==strcmp("Hello", greet.get()), "testChainedSet", "internal representation error");
greet.set("Hi").set("Buna");
assert(0==strcmp("Buna", greet.get()), "testChainedSet", "set failed");
}
My function inside the class that I wrote to solve this test is the following
char* set(const char* s){
len=strlen(s);
repres=new char(len+1);
strcpy(repres,s);
return repres;
}
I get an error when compiling the code
error: request for member 'set' in 'greet.stri::set(((const char*)"Hi"))', which is of non-class type 'char*'|
I dont understand chain linking that well, I would appreciate if somebody could point out what I'm doing wrong. Thanks in advance!
If you want to be able to chain calls you need to return a reference to the this object.
For instance
stri& set(const char* s)
{
repres = std::strdup(s);
return *this;
}
I've taken the liberty of simplifying your string duplication. I haven't fixed the memory leak that you will get if you call set when repres already contains dynamically allocated memory.
Related
I'm getting an unexpected behavior when passing a const string to a function as a parameter.
I have this function:
std::string getStatusByTopic(const std::string topic){
if (topic.compare(TOPIC_WP_SM_CMD) == 0)
return state_to_string(STATUSES::WP_HANDLER_STATUS);
}
Which is not totally implemented yet.
And I have this function:
InsertStatus(getStatusByTopic(TOPIC_WP_SM_CMD),msg);
Which declared as:
void Msp::InsertStatus(const std::string status_topic, const std_msgs::String::ConstPtr& new_status)
I have 2 questions:
These functions have been compiled successfully, even though there's a possible usage where getStatusByTopic() returns nothing when its defined returned type is string. How is it possible?
When the code is executed, with the scenario that and getStatusByTopic(TOPIC_WP_SM_CMD) returns nothing. There's no runtime errors, more over - TOPIC_WP_SM_CMD is passed as parameter to InsertStatus() (which is defined ad "/some/topic/"). How is that possible?
Thanks.
Currently, I've created a simple error handling system to check whether a pointer is valid by checking for nullptr like so:
inline void ErrReport(const char8* fileOfError, int32 lineNumberOfError, const Blz::string c_errMessage)
{
ErrorContext::LogContext();
LOG(" ERROR: %s\n", c_errMessage.c_str());
LOG(" In %s: %i\n\n", fileOfError, lineNumberOfError);
exit(0);
}
#if(_DEBUG)
#define ERRASSERT(test, msg) do {if (!(test)) Blz::Err::ErrReport(__FILE__, __LINE__, msg);} while (0)
#endif
I can then call ERRASSERT in my code like so:
unsgined char* imageData = LoadImage("PathToImage");
ERRASSERT(imageData, "Image did not load properly");
Right now, in order to do something similar with non-pointer objects I have a Check() function to see if an object has been initialized or not:
template<typename T> inline bool Check(boost::outcome::expected<T>& obj)
{
if (obj)
return true;
else
return false;
}
With this code, if I understand how to use outcome::expected correctly, I would then just call the above function within my ERRASSERT and everything should work similiarly
boost::outcome::expected<ObjectType> obj = functionReturnsObj();
ERRASSERT(Check(obj), "Object not initialized!);
My question:
Is there a better way to check if an object is initialized without having to wrap everything in boost::outcome::expected? Are there even many scenarios where an object wouldn't be initialized given C++ automatically initializes objects upon creation? Should I even be worried about this?
Is there a better way to check if an object is initialized
Don't.
Are there even many scenarios where an object wouldn't be initialized given C++ automatically initializes objects upon creation?
Yes, and it doesn't (always).
But that's the programmer's responsibility (and you can usually rely on compiler warnings to catch silly mistakes).
Should I even be worried about this?
No.
I just want to elaborate a bit on Should I even be worried about this? in addition to #BoundaryImposition's answer.
An uninitialized C++ object may cause you issues in certain cases. If you have Foo and create an instance f as below, then f.a and f.b are not initialized and you should not assume they are 0.
struct Foo { int a; int b; };
Foo f;
I'm new to multi-threading and have limited knowledge in programming. I want to use async function in c++ to call a virtual function. Snippets of the code are given below. Any help would be much appreciated.
class Binary_Genome: public Individual
{
public:
std::string evaluate_fitness();
}
class Individual
{
public:
virtual std::string evaluate_fitness()=0;
}
int main()
{
std::string w_list;
Individual* current_ind;
//Skipped some code here
std::future<std::string> future_strs;
future_strs = std::async(current_ind->evaluate_fitness); //Complier does not understand this line.
w_list = future_strs.get();
return 0;
}
Compilation error:
error: invalid use of non-static member function
I understand std::async(current_ind->evaluate_fitness) is incorrect syntax. However, I don't know what the correct syntax is. The code works perfectly without async (w_list = current_ind->evaluate_fitness()). Thanks for the help.
Even if it were to compile, you would get memory error since Individual* current_ind; doesn't initialize the pointer. currently it points to garbage memory address.
yo ucan use pointers to objects in std::async liek that:
Object obj;
Object* pointer = &obj;
auto fut = std::async([pointer]{ return pointer->returnSomthing(); });
make sure that obj is alive as long as the async function runs. std::shared_ptr is extremly suitable for that.
I have some code that looks like this:
static std::string Foo(const std::string& blah)
{
if ( someWierdEdgeCase() ){
return false; // <-- this line has a compiler error
}
std::string resourcePath;
resourcePath.append("/assets/");
return resourcePath;
}
It used to compile fine, but then I upgraded to Xcode 5.1, and now it no longer compiles. The error I get is the following one:
No viable conversion from 'bool' to 'std::string'
I would like to know what I should replace 'return false' with so that this works the way it used to.
Normally, I would be happy to return something other than false, and clearly that is not good behavior. But somehow this code used to compile and run, and I want to understand what it was doing, in case some other part of this codebase is relying on what is certainly weird behavior.
This:
return false; // <-- this line has a compiler error
There is no standard way to convert bool to std::string (please correct me if there is or was something special in gcc (the old XCode mac compiler)). This means that your code base used to contain explicit code to convert the bool to string.
If it is not compiling now this suggests this conversion was removed from your code base.
A couple of people of suggested alternatives. But I doubt any of these are going to work. As the old code had a depedency on how it used to work. So making any specific recomendation will depend on working out how the old code compiled and what it returned when someWierdEdgeCase() is true. Basically you need to replicate this behavior.
Otherwise you need to hunt down all used cases in your code and change the behavior to match the new behavior. In this case I would change the name of the function. Re-Compile and see where the code breaks and check the behavior at each location and make sure it behaves the same.
static std::string Foo(const std::string& blah)
{
std::string resourcePath = "";
if ( someWierdEdgeCase() ){
return resourcePath; // <-- Now you're returning a string
}
resourcePath.append("/assets/");
return resourcePath;
}
If you need the return type to be - for whatever reason - not always present, return by pointer, instead of returning by value.
static yourType* Foo(const std::string& blah){
if ( someWierdEdgeCase() ){
return 0;
}
}
Then you can test and assign the function in the same line
yourType* result;
if(result = Foo("something")){
// the result was correct
Of course - since your function returns a std::string, you can return an empty string (""), or - also independent of the return type - throw an exception.
I had same issue that with the fact that my interface file and implementation file were using different data types in method declaration.Putting same data type on both place in method declaration error went away.
I'm writing a few CXX unit tests for a class I have written. I have never written CXX tests before (also this is the only framework I can use). I am trying to call a function contained within my class so that I can test the output is what is expected, but I am unsure if you can do this, and if so, how.
Test.h:
class Test..... {
public:
std::string GenerateHash(const std::string& user, const std::string& url) const;
...
}
Test.cpp:
string
Test::GenerateHash(const string& user, const string& urrl) const {
...
}
I have included the header file in the CXX test, but cannot access the GenerateHash function.
Test.cxx_h:
void testCheckHashGeneration( void ) {
TS_ASSERT_EQUALS (GenerateHash("testuser", "http://www.stackoverflow.com"), "DFEGEC.....");
}
Error: error: âGenerateHashâ was not declared in this scope
I also tried:
Test.cxx_h:
void testCheckHashGeneration( void ) {
Test test;
TS_ASSERT_EQUALS (test->GenerateHash("testuser", "http://www.stackoverflow.com"), "DFEGEC.....");
}
Error: error: âTestâ has not been declared
Any help will be greatly appreciated.
In the first case, you're trying to call a member function without an instance of Test. You need a Test to call it on, as you've done in the second case.
In the second case, you're trying to call a member using the syntax for having a pointer to the object, '->', when you actually have an object. You want the second to look like this:
test.GenerateHash(...)
If you somehow had a Test*, then you could call it like
test->GenerateHash(...)
use . for objects, -> for pointers to objects.
More code and error output would be helpful.
If the GenerateHash function can be a static method, then make it static. Then call it using Test::GenerateHash(/*your arguments*/);
Considering the way you initially attempted to call GenerateHash, I would guess that this should be a static method. If its execution does not depend on a particular instance of the Test class, then it can be static.
Otherwise, use test.GenerateHash rather than test->GenerateHash