My problem seems to be very basic but I could not find a solution for it. I need to write a code which helps debugging by reporting the line and location of exception throwing. The problem is that __LINE__ is an int value and I have problem with its conversion into string in the following code where std::string(line) is used:
#pragma once
#include <stdexcept>
#include <cstring>
class CRuntime_error_line: public std::runtime_error
{
public:
CRuntime_error_line(const char * msg, const char * file,int line)
:runtime_error(std::string(msg)+" #"+":"+std::string(line)){}
};
#define runtime_error_line(msg) CRuntime_error_line(msg,__FILE__,__LINE__)
Seems std::string(line) cannot convert int to string and other solutions suggested online cannot be implemented inline and I don't know how to call a base constructor in second line!
compiler output:
log.h: In constructor ‘CRuntime_error_line::CRuntime_error_line(const
char*, const char*, int)’: log.h:10:124: error: invalid conversion
from ‘int’ to ‘const char*’ [-fpermissive] CRuntime_error_line(const
char * msg, const char * file,int
line):runtime_error(std::string(msg)+" #"+":"+std::string(line)){}
(Using g++ and linux environment)
edit:
the macro is supposed to be called this way:
throw runtime_error_line("Invalid somethihng ...!");
As is suggested by Borgleader std::to_string is your solution. It will also construct a temporary std::string for you, so there's no need to construct a temporary string from msg:
#pragma once
#include <stdexcept>
#include <cstring>
#include <string> // Add this to support std::to_string
class CRuntime_error_line: public std::runtime_error
{
public:
CRuntime_error_line(const char* msg, const char* file, int line)
: runtime_error(msg + " #:"s + std::to_string(line)){} // Use std::to_string here
};
#define runtime_error_line(msg) CRuntime_error_line(msg, __FILE__, __LINE__)
Without C++11 you can still do this it's just not as clean:
#pragma once
#include <stdexcept>
#include <cstring>
#include <sstream> // Use to include std::ostringstream
class CRuntime_error_line: public std::runtime_error
{
public:
CRuntime_error_line(const char* msg, const char* file, int line)
: runtime_error(static_cast<std::ostringstream&>(std::ostringstream() << msg << " #:" << line).str()){} // Use std::ostringstream here
};
#define runtime_error_line(msg) CRuntime_error_line(msg, __FILE__, __LINE__)
int this case may be better :
#define STRING_DEFINE1(x) #x
#define STRING_DEFINE(x) STRING_DEFINE1(x)
...
CRuntime_error_line(msg,__FILE__,STRING_DEFINE(__LINE__))
The simplest thing I can think of would be to write a to_string yourself:
#include <sstream>
std::string to_string(int i)
{
std::ostringstream os;
os << i;
return os.str();
}
Then call it as others have suggested.
Related
I'm trying to convert const std::filesystem::directory_entry (dirent) to tchar but I don't understand how it an be done. I tried a lot of ways. Can you help me?
Edited:
#include "pch.h"
#include <memory>
#include <filesystem>
#include <algorithm>
#include <iostream>
#include <tchar.h>
#include <string.h>
typedef wchar_t WCHAR;
namespace fs = std::filesystem;
int main() try
{
std::for_each(fs::recursive_directory_iterator("./foo/"), {},
[](fs::directory_entry const& dirent)
{
if (fs::is_regular_file(dirent) &&
dirent.path().filename() == "black.txt")
{
std::wstring = path.wstring();
}
});
}
catch (fs::filesystem_error const& e)
{
std::cerr << "error: " << e.what() << '\n';
}
You can convert std::filesystem::path to any form using these functions:
std::string string() const;
std::wstring wstring() const;
std::u16string u16string() const;
std::u32string u32string() const;
TCHAR is somewhat of a relic as mentioned in the comments, and you're much better off using any of the above alternatives.
If you're going to pass it to Win32 API functions, I would either suggest using wstring explicitly and not bother with the shape-shifting TCHAR at all.
What your code should look like is this:
if (fs::is_regular_file(dirent) &&
dirent.path().filename() == "black.txt")
{
std::wstring path_as_string = path.wstring();
}
No TCHAR, no C-style arrays no C-style memory copying.
I am trying to learn C++, however, the parameter to a method I have in my own class is misbehaving. When it uses a dataType of 'int', it works fine with no errors, but when I attempt to change it to a 'string' dataType, the program crashes with this error.
Error 1 error C2061: syntax error : identifier 'string' in temp.h ln
8 col 1
The classes I am using are as follows:
WORKING CODE
TesterClass.cpp // Entry Point
#include "stdafx.h"
#include "Temp.h"
int _tmain(int argc, _TCHAR* argv[])
{
Temp tmp;
tmp.doSomething(7);
return 0;
}
Temp.h
#pragma once
class Temp
{
public:
Temp();
void doSomething(int blah);
};
Temp.cpp
#include "stdafx.h"
#include "Temp.h"
#include <iostream>
#include <string>
using std::string;
Temp::Temp()
{
std::cout << "Entry" << std::endl;
string hi;
std::cin >> hi;
std::cout << hi << std::endl;
}
void Temp::doSomething(int blah)
{
std::cout << blah;
}
BROKEN CODE
Temp.h
#pragma once
class Temp
{
public:
Temp();
void doSomething(string blah);
};
Temp.cpp
#include "stdafx.h"
#include "Temp.h"
#include <iostream>
#include <string>
using std::string;
Temp::Temp()
{
std::cout << "Entry" << std::endl;
string hi;
std::cin >> hi;
std::cout << hi << std::endl;
}
void Temp::doSomething(string blah)
{
std::cout << blah;
}
When I adjust the parameter 'blah' to be a string, in both the .h and .cpp file, the problem occurs.
I have looked around, but none of the answers seem to solve my problem. I would greatly love help on this an I am out of ideas. I have tried reinstalling C++, messing with:
using namepace std;
using std::string;
std::string instead of string
etc.
If you know how to solve my problem I would love to hear from you. I am more than happy to provide more information.
C++ performs single-pass compilation, so std::string needs to be declared before you use it at all - including in the header file.
// Temp.h
#pragma once
#include <string>
class Temp
{
public:
Temp();
void doSomething(std::string blah);
};
I would encourage you to be specific in your header files when specifying classes like this, because you might easily come across another library that defines it's own string and then you would run into naming conflicts. Save the using import statements for your cpp files.
πάντα ῥεῖ had the write answer, thankyou!
They said to use std::string when needed, and to also #include <string> in the header file.
I've read several similar questions here that have been answered, but I don't grok yet, so please bear that in mind before closing as duplicate :). I want a simple Log object with a Print() method. If Log is constructed with no parameters, logging is to cout. Otherwise, parameters describe a file to which logging is done.
(I suspect part of the problem is understanding the relationship between all the stream classes.)
When compiled, error is:
Log.cpp:11:23: error: invalid initialization of reference of type ‘std::ofstream& {aka std::basic_ofstream<char>&}’ from expression of type ‘std::ostream {aka std::basic_ostream<char>}’
Log.h:
#ifndef LOG_H
#define LOG_H
#include <string>
#include <fstream>
class Log {
public:
Log();
Log(const char*, const char*);
void Print(const char* msg,...);
private:
// instance contains a reference to ostream
std::ofstream& output_stream;
};
#endif
Log.cpp:
#include "Log.h"
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
#include <fstream>
// Constructor w/no parms = log to cout
Log::Log() :
output_stream(cout)
{}
// Constructor w/parms = log to file
Log::Log(const char* dir, const char* file) {
string output_file_name = string(dir) + "/" + string(file);
output_stream.open(output_file_name.c_str(), std::ofstream::out);
}
// Print() sends output to the stream (we'll do printf semantics later)
void
Log::Print(const char* msg,...) {
output_stream << msg << endl;
}
cout is not of type ofstream, so you cannot bind an ofstream reference to it. output_stream should be type ostream& instead, which will allow it to refer to either cout and a file stream, since ofstream is a subclass of ostream.
Also, in the case that the user provides a filename, you still need something for the reference to refer to, you can't just use it as is. I recommend that you store an actual ofstream object, (or a unique_ptr<ofstream>), and make output_stream refer to it. Make sure you declare the ofstream object before the ostream reference in your class definition, otherwise you will have undefined behavior when you try to bind the reference in the initialization list. Or you can make it a pointer, instead of a reference, and assign it in the body of the constructor.
I suggest shuffling filebufs or other streambufs.
#include <string>
#include <ostream>
#include <fstream>
class Log {
public:
Log();
Log(const char*, const char*);
void Print(const char* msg,...);
private:
// instance contains a reference to ostream
std::ostream output_stream;
std::ofstream _file;
};
And the cpp:
#include <iostream>
#include <string>
#include <fstream>
// Constructor w/no parms = log to cout
Log::Log()
: output_stream(std::cout.rdbuf())
{}
// Constructor w/parms = log to file
Log::Log(const char* dir, const char* file)
: output_stream(nullptr)
{
std::string output_file_name = std::string(dir) + "/" + std::string(file);
_file.open(output_file_name.c_str(), std::ofstream::out);
output_stream.rdbuf(_file.rdbuf());
}
// Print() sends output to the stream (we'll do printf semantics later)
void Log::Print(const char* msg,...) {
output_stream << msg << std::endl;
}
I have a file named global.h whose contents are:
#define DEPTH 10
#define LOGGING //to log the progress of the program.
#ifdef LOGGING
#include <fstream>
#include <string>
extern std::string logFileName;
extern std::ofstream logFileObj;
#endif
Also main.cpp:
#include "global.h"
using namespace std;
#ifdef LOGGING
string logFileName = ".log";
ofstream logFileObj;
logFileObj.open(logFile); //line 13
logFileObj<<"depth: "<<DEPTH<<endl; //line 14
#endif
I am constantly getting the following error in compilation:
src/main.cpp:13:1: error: ‘logFileObj’ does not name a type
src/main.cpp:14:1: error: ‘logFileObj’ does not name a type
Any help appreciated.
C++ does not allow operation outside function. C++ allows you define variable globally but you need to put operations inside functions.
If I read your question correctly, you just need a function and call it when you need to:
#include <fstream>
#include <utility>
#include <string>
template<typename T>
void WriteLog(const std::string& log_file_name, const std::string& prefix, const T& data)
{
std::ofstream log_file_handler(log_file_name.c_str(), std::ios::app); // if you use C++11, you could use string directly
log_file_handler << prefix << data << std::endl;
}
usage:
WriteLog<int>("app.log", "depth:", DEPTH);
I'm pretty sure I've included the qanda class, but when I try to declare a vector that contains it or a class of that type I get an error saying that qanda is undefined. Any idea what the problem might be?
bot_manager_item.h
#pragma once
#include "../bot_packet/bot_packet.h"
#include <vector>
class bot_manager_item;
#include "qanda.h"
#include "bot_manager.h"
class bot_manager_item
{
public:
bot_manager_item(bot_manager* mngr, const char* name, const char* work_dir);
~bot_manager_item();
bool startup();
void cleanup();
void on_push_event(bot_exchange_format f);
bool disable;
private:
void apply_changes();
bot_manager *_mngr;
std::string _name;
std::string _work_dir;
std::string _message;
std::string _message_copy;
std::vector<qanda> games;
qanda test;
char _config_full_path[2600];
};
qanda.h
#ifndef Q_AND_A
#define Q_AND_A
#include "users.h"
#include "..\bot_packet\bot_packet.h"
#include "bot_manager.h"
#include <string>
#include <algorithm>
#include <map>
#include <vector>
#include <fstream>
class qanda
{
public:
qanda(bot_manager * manager, std::string name, std::string directory);
~qanda(){};
void room_message(std::string username, std::string user_message);
void timer_tick();
private:
// data members
std::string question;
std::string answer;
std::string directory;
std::string command_prefix;
std::string name;
Users users;
std::map <std::string, std::string> questions_and_answers;
int time_per_question; // seconds
int time_between_questions; // seconds
int timer; // milliseconds
bool is_delayed;
bool is_playing;
bot_manager * manager;
// functions
void new_question();
void send_message(std::string msg);
void announce_question();
void load_questions();
};
#endif
Solved: I ended up refactoring the code in such a way as to avoid the use of bot_manager within the qanda class.
I suspect a circular #include problem. Is it possible qanda.h indirectly includes bot_manager_item.h?
It looks like you may be able to reduce header dependencies by using a forward declaration
class bot_manager;
instead of #include "bot_manager.h" in one or both of your posted header files.