I have a problem that is puzzling me, something is missing from my c++ understanding.
I'm trying to construct an object with a boost::filesystem::path (which itself is constructed from a basic_string) I thought I could save a line of code by doing the construction of the boost path on the same line as I construct my object.
See the example below:
One thing that i don't understand is that, although it doesn't work, I also get no errors. i.e. nothing seems to happen. Why would that be?
class Test {
public:
Test(boost::filesystem::path in) {
std::cout << "Succesful construction" << std::endl;
}
};
int main() {
std::string str("asdf.txt");
boost::filesystem::path p(str);
Test test1(boost::filesystem::path(str)); // Nothing at all happens, but no error
Test test2(p); // "Succesful construction"
}
This is C++'s so-called "most vexing parse." The problem you're running into is that this:
Test test1(boost::filesystem::path(str));
is a declaration for a function named test1 that returns a Test and takes one argument of type boost::filesystem::path named str. The parentheses around str are parsed as superfluous, so the line is interpreted as equivalent to:
Test test1(boost::filesystem::path str);
If you're compiling with C++11, you can replace the outer parentheses with braces:
Test test1{boost::filesystem::path(str)};
Pre-C++11, you can use an extra set of parentheses:
Test test1((boost::filesystem::path(str)));
Related
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.
This might be a very silly question, but I don't even know what should I write to look for answers. I'm not even sure if the title I gave is correct.
If I have a constructor like this:
CError(const std::string& msg) { showMessage(msg) }
And I'd like to call it like this ...
CError("some message");
... everything works, but when string is specified in some variable, I got an error that "Default constructor for class CError doesn't exist":
std::string str = "some message";
CError(str);
When I write it like this, it works:
std::string str = "some message";
CError err(str);
But I just don't need this err object.
Could anyone explain me why can't I call only constructor itself?
Thanks in advance for the answers.
The line CError(str); is parsed as CError str;, which defines a new variable, str. My compiler fails differently, which makes the problem more obvious: redefinition of 'str' with a different type.
A simple work-around for this problem is to cast the object:
(void)CError(str);
The burning question, however, is: why do this? If you don't plan to use the constructed object in any way, why not simply make it a static member function or even just a plain old free function?
The statement CError(str); is read as defining an object str of type CError; it's equivalent to CError str; but with the name str parenthesized.
To work around this you can parenthesize the type name as well: (CError)(str);. This forces the statement to be read as a functional-cast expression; you could equivalently write (CError) str; or even static_cast<CError>(str);.
In C++11 you can use universal initialization syntax to write CError{str};.
'initPhysics' was not declared in this scope.
I have simplified my program as much as I could; here it is:
helloworld.hpp
#ifndef HELLOWORLD_HPP
#define HELLOWORLD_HPP
class testWorld {
public:
testWorld() {}
~testWorld() {}
void initPhysics();
};
#endif
hello.cpp
#include "helloworld.hpp"
#include <iostream>
using namespace std;
void testWorld::initPhysics() {
cout << "Initiating physics..." << endl;
}
int main(int argc,char** argv) {
cout << "Hello World!" << endl;
testWorld* world;
world = new testWorld();
world<-initPhysics();
return 0;
}
I compile with the command
g++ -c hello.cpp
and get the error
hello.cpp: In function ‘int main(int, char**)’:
hello.cpp:14:21: error: ‘initPhysics’ was not declared in this scope
Why doesn't the compiler see the declaration of initPhysics, even though I included helloworld.hpp?
It should be world->initPhysics(), not world<-initPhysics()
Your version is being read as the expression "world is less than -1 multiplied by the result of the global function initPhysics()" and it's that global function that it can't find.
And although this is obviously test code, I'd just like to point out that if you allocate an object with new, you must explicitly delete it somewhere.
world<-initPhysics() should be world->initPhysics()?
Learn to read the -> operator (not <-!) in ptr->member as "member in whatever ptr points to", in other words: it is a somewhat literal representation of an actual pointer. So in your case it should be
world->initPhysics(); // note the ->, not <-
However, while this answers your question, it's far from sufficient. There's several other problems with your code.
There's no need to first create an uninitialized pointer, and then initialize it. That's error-prone, and you should instead initialize it immediately:
testWorld* world = new testWorld();
world->initPhysics();
Note that in C++ every object created using the new operator needs to be destroyed explicitly using the delete operator:
delete world; // sounds scary, BTW
You seem to be coming from a language like Java or C#, where everything must be new'd. In C++ this is not true. By default you should create objects on the stack, rather than on the heap:
testWorld world;
world.initPhysics();
But there's still a problem with your code. What you have now is what's known as two-phase construction. As a user of your class I need to remember to call an initialization function before I use an instance of it. But that's what constructors are for! A constructor should fully initialize an object, so that it is in a usable state. You should call your initialization function from the constructor instead:
testWorld() {initPhysics();}
Physics is an integral part of the world, and shouldn't be added as an afterthought. :)
You want world->initPhysics(); instead of world<-initPhysics();
world<-initPhysics();
Here, your arrow is in the wrong direction. You should have :
world->initPhysics();
world<-initPhysics(); should be world->initPhysics();
I am looking for a portable way to implement lazy evaluation in C++ for logging class.
Let's say that I have a simple logging function like
void syslog(int priority, const char *format, ...);
then in syslog() function we can do:
if (priority < current_priority)
return;
so we never actually call the formatting function (sprintf).
On the other hand, if we use logging stream like
log << LOG_NOTICE << "test " << 123;
all the formating is always executed, which may take a lot of time.
Is there any possibility to actually use all the goodies of ostream (like custom << operator for classes, type safety, elegant syntax...) in a way that the formating is executed AFTER the logging level is checked ?
This looks like something that could be handled with expression templates. Beware, however, that expression templates can be decidedly non-trivial to implement.
The general idea of how they work is that the operators just build up a temporary object, and you pass that temporary object to your logging object. The logging object would look at the logging level and decide whether to carry out the actions embodied in the temporary object, or just discard it.
What I've done in our apps is to return a boost::iostreams::null_stream in the case where the logging level filters that statement. That works reasonably well, but will still call all << operators.
If the log level is set at compile time, you could switch to an object with a null << operator.
Otherwise, it's expression templates as Jerry said.
The easiest and most straight-forward way is to simply move the check outside of the formatting:
MyLogger log; // Probably a global variable or similar.
if (log.notice())
log << "notified!\n" << some_function("which takes forever to compute"
" and which it is impossible to elide if the check is inside log's"
" op<< or similar");
if (log.warn()) {
log << "warned!\n";
T x;
longer_code_computing(value_for, x); // easily separate out this logic
log << x;
}
If you really wanted to shorten the common case, you could use a macro:
#define LOG_NOTICE(logger) if (logger.notice()) logger <<
LOG_NOTICE(log) << "foo\n";
// instead of:
if (log.notice()) log << "foo\n";
But the savings is marginal.
One possible MyLogger:
struct MyLogger {
int priority_threshold;
bool notice() const { return notice_priority < current_priority; }
bool warn() const { return warn_priority < current_priority; }
bool etc() const { return etc_priority < current_priority; }
template<class T>
MyLogger& operator<<(T const &x) {
do_something_with(x);
return *this;
}
};
The problem here is mixing iostream-style operator overloading with a printf-like logging function – specifically translating manipulators and formatting flags/fields from iostreams into a format string. You could write to a stringstream and then chunk that to your syslog function, or try something fancier. The above MyLogger works easiest if it also contains an ostream reference to which it can forward, but you'll need a few more op<< overloads for iomanips (e.g. endl) if you do that.
For mine I made a debug_ostream class which has templated << operators. These operators check the debug level before calling the real operator.
You will need to define non-template overrides for const char* and std::ostream& (*x)(std::ostream&) because otherwise those don't work. I'm not sure why.
With inlining and high enough optimization levels the compiler will turn the whole output line into a single check of the debug level instead of one per output item.
I should add to this that this doesn't solve the original problem. For example if part of the debug line is to call an expensive function to get a value for output, that function will still be called. My solution only skips the formatting overhead.
I have a logger class. Call it MyLogger. I may use it in a function like this:
void MyFunc(MyLogger& oLogger)
{
//Do stuff
oLogger.Log("In MyFunc : Some Error");
//Do something else
oLogger.Log("In MyFunc : Some other error");
}
Now, I want to prepend "In MyFunc" to the logs if the log comes from inside MyFunc. Similarly for other functions...
Because this is tiresome, I tried something like this:
void MyLogger::PushPrependString(const char*)
{
//Store prepend string in stack and set it as current prepend string.
}
void MyLogger::PopPrependString()
{
//Pop the most recent prepend string.
}
Now, I can use these two functions like this:
void MyFunc(MyLogger& oLogger)
{
oLogger.PushPrependString("In MyFunc : ");
//Do stuff
oLogger.Log("Some Error");
//Do something else
oLogger.Log("Some other error");
oLogger.PopPrependString();
}
The trouble is, if there are multiple returns in a function, this becomes ugly. Is there any way around this? Is this a common problem? Is there any preprocessor macro like __FILE__ or __LINE__ for getting the name of the function a line appears in? Any comments would be appreciated. Thanks.
"The trouble is, if there are multiple returns in a function, this becomes ugly. Is there any way around this?"
Yes, just use an object with constructor (calls PushPrependString) and destructor (calls PopPrependString).
class LogPrefix
{
private:
MyLogger* logger_;
LogPrefix( LogPrefix const& ); // No such.
LogPrefix& operator=( LogPrefix const& ); // No such.
public:
LogPrefix( MyLogger& logger, char const s[] )
: logger_( &logger )
{
logger_->PushPrependString( s );
}
~LogPrefix()
{
logger_->PopPrependString();
}
};
Disclaimer: off the cuff code, not touched by compiler's hands...
"Is this a common problem?"
Yes.
"Is there any preprocessor macro like FILE or LINE for getting the name of the function a line appears in?"
Not in C++98. Various compilers offer various extensions that do that. IIRC C++0x adopts the C99 scheme, which unfortunately just provides static strings.
Cheers & hth.
RAII - Resource Acquisition Is Initialization.
In this case, you create an object on entry to the function that identifies the current function to the logging system; when the function exits (by any return or by exception thrown or by exception not caught), the object will be destroyed, and the destructor changes what is printed in future by the logging system.
In C99, and maybe in some C++ compilers such as G++, there is a predefined variable, __func__ containing the function name. The C++ equivalent is more complex, I believe.