Use variable from CMAKE in C++ - c++

I want to use a value declared in my CMakeLists.txt in my C++ code. I've tried to do like that :
ADD_DEFINITIONS( -D_MYVAR=1 )
and
#if -D_MYVAR == 1
#define var "someone"
#else
#define var "nobody"
#endif
int main(){
std::cout << "hello" << var << std::endl;
return 0;
}
But it doesn't work, and I don't understand why. Maybe I don't use ADD_DEFINITIONS correctly...
Ideally, I wish do something like that :
ADD_DEFINITIONS( -D_MYVAR=\"someone\" )
and
#define var D_MYVAR
int main(){
std::cout << "hello" << var << std::endl;
return 0;
}
Is it possible ?
Thanks !

add_definitions ( -DVARNAME=... )
is the correct way of using add_definitions.
To check for a constant then, use
#ifdef VARNAME
...
#endif

Thanks to πάντα ῥεῖ
His solution works for my first question, and I've could do that :
CMakeLists.txt:
ADD_DEFINITIONS( -D_VAR=\"myValue\" )
main.cpp:
#include <iostream>
#ifdef _VAR
#define TXT _VAR
#else
#define TXT "nobody"
#endif
int main(){
std::cout << "hello " << TXT << " !" << std::endl;
return 0;
}

Actually there is a much more elegant way to do this, that does not require to go through the C/C++ preprocessor. (I hate #ifdef...)
In CMakeLists.txt:
set( myvar "somebody" )
# Replaces occurrences of #cmake_variable# with the variable's contents.
# Input is ${CMAKE_SOURCE_DIR}/main.cpp.in,
# output is ${CMAKE_BINARY_DIR}/main.cpp
configure_file( main.cpp.in main.cpp #ONLY )
In main.cpp.in:
#include <iostream>
int main(){
// myvar below gets replaced
std::cout << "hello #myvar#" << std::endl;
return 0;
}
Note, however, that a file so configured gets saved in ${CMAKE_BINARY_DIR}, so you have to prefix it as such when listing it in the source files (as those default to ${CMAKE_SOURCE_DIR}):
add_library( myproject foo.cpp bar.cpp ${CMAKE_BINARY_DIR}/main.cpp )

As of CMake 3.12 add_definitions has been superseeded by other alternatives.
For this question, you should use add_compile_definitions in the same way you were using add_definitions:
add_compile_definitions( MY_VAR )
(note that the -D is not needed anymore).
And then in your *.cpp file:
#ifdef MY_VAR
// do something if var defined
#endif

Related

How do change the default directory for file creation? [duplicate]

How can I change my current working directory in C++ in a platform-agnostic way?
I found the direct.h header file, which is Windows compatible, and the unistd.h, which is UNIX/POSIX compatible.
The chdir function works on both POSIX (manpage) and Windows (called _chdir there but an alias chdir exists).
Both implementations return zero on success and -1 on error. As you can see in the manpage, more distinguished errno values are possible in the POSIX variant, but that shouldn't really make a difference for most use cases.
Now, with C++17 is possible to use std::filesystem::current_path:
#include <filesystem>
int main() {
auto path = std::filesystem::current_path(); //getting path
std::filesystem::current_path(path); //setting path
}
For C++, boost::filesystem::current_path (setter and getter prototypes).
A file system library based on Boost.Filesystem will be added to the standard.
This cross-platform sample code for changing the working directory using POSIX chdir and MS _chdir as recommend in this answer. Likewise for determining the current working directory, the analogous getcwd and _getcwd are used.
These platform differences are hidden behind the macros cd and cwd.
As per the documentation, chdir's signature is int chdir(const char *path) where path is absolute or relative. chdir will return 0 on success. getcwd is slightly more complicated because it needs (in one variant) a buffer to store the fetched path in as seen in char *getcwd(char *buf, size_t size). It returns NULL on failure and a pointer to the same passed buffer on success. The code sample makes use of this returned char pointer directly.
The sample is based on #MarcD's but corrects a memory leak. Additionally, I strove for concision, no dependencies, and only basic failure/error checking as well as ensuring it works on multiple (common) platforms.
I tested it on OSX 10.11.6, Centos7, and Win10. For OSX & Centos, I used g++ changedir.cpp -o changedir to build and ran as ./changedir <path>.
On Win10, I built with cl.exe changedir.cpp /EHsc /nologo.
MVP solution
$ cat changedir.cpp
#ifdef _WIN32
#include <direct.h>
// MSDN recommends against using getcwd & chdir names
#define cwd _getcwd
#define cd _chdir
#else
#include "unistd.h"
#define cwd getcwd
#define cd chdir
#endif
#include <iostream>
char buf[4096]; // never know how much is needed
int main(int argc , char** argv) {
if (argc > 1) {
std::cout << "CWD: " << cwd(buf, sizeof buf) << std::endl;
// Change working directory and test for success
if (0 == cd(argv[1])) {
std::cout << "CWD changed to: " << cwd(buf, sizeof buf) << std::endl;
}
} else {
std::cout << "No directory provided" << std::endl;
}
return 0;
}
OSX Listing:
$ g++ changedir.c -o changedir
$ ./changedir testing
CWD: /Users/Phil
CWD changed to: /Users/Phil/testing
Centos Listing:
$ g++ changedir.c -o changedir
$ ./changedir
No directory provided
$ ./changedir does_not_exist
CWD: /home/phil
$ ./changedir Music
CWD: /home/phil
CWD changed to: /home/phil/Music
$ ./changedir /
CWD: /home/phil
CWD changed to: /
Win10 Listing
cl.exe changedir.cpp /EHsc /nologo
changedir.cpp
c:\Users\Phil> changedir.exe test
CWD: c:\Users\Phil
CWD changed to: c:\Users\Phil\test
Note: OSX uses clang and Centos gnu gcc behind g++.
Does chdir() do what you want? It works under both POSIX and Windows.
You want chdir(2). If you are trying to have your program change the working directory of your shell - you can't. There are plenty of answers on SO already addressing that problem.
Did you mean C or C++? They are completely different languages.
In C, the standard that defines the language doesn't cover directories. Many platforms that support directories have a chdir function that takes a char* or const char* argument, but even where it exists the header where it's declared is not standard. There may also be subtleties as to what the argument means (e.g. Windows has per-drive directories).
In C++, googling leads to chdir and _chdir, and suggests that Boost doesn't have an interface to chdir. But I won't comment any further since I don't know C++.
Nice cross-platform way to change current directory in C++ was suggested long time ago by #pepper_chico. This solution uses boost::filesystem::current_path().
To get the current working directory use:
namespace fs = boost::filesystem;
fs::path cur_working_dir(fs::current_path());
To set the current working directory use:
namespace fs = boost::filesystem;
fs::current_path(fs::system_complete( fs::path( "new_working_directory_path" ) ));
Bellow is the self-contained helper functions:
#include "boost/filesystem/operations.hpp"
#include "boost/filesystem/path.hpp"
#include <string>
namespace fs = boost::filesystem;
fs::path get_cwd_pth()
{
return fs::current_path();
}
std::string get_cwd()
{
return get_cwd_pth().c_str();
}
void set_cwd(const fs::path& new_wd)
{
fs::current_path(fs::system_complete( new_wd));
}
void set_cwd(const std::string& new_wd)
{
set_cwd( fs::path( new_wd));
}
Here is my complete code-example on how to set/get current working directory:
#include "boost/filesystem/operations.hpp"
#include "boost/filesystem/path.hpp"
#include <iostream>
namespace fs = boost::filesystem;
int main( int argc, char* argv[] )
{
fs::path full_path;
if ( argc > 1 )
{
full_path = fs::system_complete( fs::path( argv[1] ) );
}
else
{
std::cout << "Usage: tcd [path]" << std::endl;
}
if ( !fs::exists( full_path ) )
{
std::cout << "Not found: " << full_path.c_str() << std::endl;
return 1;
}
if ( !fs::is_directory( full_path ))
{
std::cout << "Provided path is not a directory: " << full_path.c_str() << std::endl;
return 1;
}
std::cout << "Old current working directory: " << boost::filesystem::current_path().c_str() << std::endl;
fs::current_path(full_path);
std::cout << "New current working directory: " << boost::filesystem::current_path().c_str() << std::endl;
return 0;
}
If boost installed on your system you can use the following command to compile this sample:
g++ -o tcd app.cpp -lboost_filesystem -lboost_system
Can't believe no one has claimed the bounty on this one yet!!!
Here is a cross platform implementation that gets and changes the current working directory using C++. All it takes is a little macro magic, to read the value of argv[0], and to define a few small functions.
Here is the code to change directories to the location of the executable file that is running currently. It can easily be adapted to change the current working directory to any directory you want.
Code :
#ifdef _WIN32
#include "direct.h"
#define PATH_SEP '\\'
#define GETCWD _getcwd
#define CHDIR _chdir
#else
#include "unistd.h"
#define PATH_SEP '/'
#define GETCWD getcwd
#define CHDIR chdir
#endif
#include <cstring>
#include <string>
#include <iostream>
using std::cout;
using std::endl;
using std::string;
string GetExecutableDirectory(const char* argv0) {
string path = argv0;
int path_directory_index = path.find_last_of(PATH_SEP);
return path.substr(0 , path_directory_index + 1);
}
bool ChangeDirectory(const char* dir) {return CHDIR(dir) == 0;}
string GetCurrentWorkingDirectory() {
const int BUFSIZE = 4096;
char buf[BUFSIZE];
memset(buf , 0 , BUFSIZE);
GETCWD(buf , BUFSIZE - 1);
return buf;
}
int main(int argc , char** argv) {
cout << endl << "Current working directory was : " << GetCurrentWorkingDirectory() << endl;
cout << "Changing directory..." << endl;
string exedir = GetExecutableDirectory(argv[0]);
ChangeDirectory(exedir.c_str());
cout << "Current working directory is now : " << GetCurrentWorkingDirectory() << endl;
return 0;
}
Output :
c:\Windows>c:\ctwoplus\progcode\test\CWD\cwd.exe
Current working directory was : c:\Windows
Changing directory...
Current working directory is now : c:\ctwoplus\progcode\test\CWD
c:\Windows>

using stream to log information in C++

I have a C++ class which logs messages to a std::ofstream. In the class definition is this code:
#ifdef NDEBUG
#define FOO_LOG(msg) /* calls to log messages are no-op in release mode */
#else
std::ofstream log_stream;
#define FOO_LOG(msg) if (log_stream.is_open()) { log_stream << msg << std::endl; }
#endif
The constructor for that class has several things it checks, and in certain situations will open the log file similar to this:
#ifndef NDEBUG
log_stream.open("output.log");
#endif
Then in the code, it calls the C macro like this:
FOO_LOG("stuff=" << stuff << " in loop counter #" << xyz)
It is convenient that you can pass multiple params to the FOO_LOG() macro. There are obvious limitations, like when logging messages from multiple threads, but this is only used for simple logging in debug builds.
What I want to know is whether there is a different/better way to deal with the msg parameter in C++? Is there a simpler/cleaner way to implement something similar to FOO_LOG() in C++?
Instead of having #ifdef NDEBUG everywhere in your code you can have a #ifdef NDEBUG at the start of the header to define other useful macros.
For me FOO_LOG("stuff=" << stuff << " in loop counter #" << xyz); feels a bit unnatural. I would have to keep reffering back to the macro definition to see how it's implemented. Instead you can define a macro to behave as an std::ostream and use it as you would any other stream. That way you can do stuff like LOG_STREAM << "stuff=" << stuff << " in loop counter #" << xyz << std::endl;.
For this answer I had some inspiration from this question.
#include <fstream>
#define NDEBUG
//An ostream class that does nothing
class DummyStream : public std::ostream {
public:
int overflow(int c) { return c; }
} dummyStream;
//Here we let NDEBUG define other macros.
#ifdef NDEBUG
std::ofstream logStream;
std::ostream& oLogStream(*(std::ostream*)&logStream);
#define LOG_STREAM (logStream.is_open() ? oLogStream : dummyStream)
#define OPEN_LOG(log) (logStream.is_open() ? logStream.close(), logStream.open(log, std::ofstream::out | std::ofstream::app) : \
logStream.open(log, std::ofstream::out | std::ofstream::app))
#define CLOSE_LOG() (logStream.close())
#else
#define LOG_STREAM (dummyStream)
#define OPEN_LOG(log) //no-op
#define CLOSE_LOG() //no-op
#endif // NDEBUG
int main(int argc, char* argv[]) {
//will only log if NDEBUG is defined.
OPEN_LOG("log.txt");
std::string stuff("stuff to log");
for(int xyz = 0; xyz < 4; xyz++) {
LOG_STREAM << "stuff=" << stuff << " in loop counter #" << xyz << std::endl;
}
CLOSE_LOG();
//Log is not open so it will not log anything.
stuff = "stuff to not log";
for(int xyz = 0; xyz < 4; xyz++) {
LOG_STREAM << "stuff=" << stuff << " in loop counter #" << xyz << std::endl;
}
return 0;
}
Benifits of this?
LOG_STREAM is treated more intuitively like any other stream.
OPEN_LOG(log) will close already open logs before opening a new one and when NDEBUG is not define it will do nothing.
CLOSE_LOG() will close a log and when NDEBUG is not define it will do nothing.
Don't need to type #ifdef NDEBUG ... #endif everywhere.
dummyStream can be replaced with something like std::cout or some other stream.
Down side?
You have this DummyStream that's just in your code and a few no-op's are performed when LOG_STREAM is used when NDEBUG is not defined.

Extremely simple test library

Is there easily embeddable C++ test lib with a friendly license? I would like a single header file. No .cpp files, no five petabytes of includes. So CppUnit and Boost.Test are out.
Basically all I want is to drop single file to project tree, include it and be able to write
testEqual(a,b)
and see if it fail. I'd use assert, but it doesn't work in non-debug mode and can't print values of a and b, and before rewriting assert I'd rather search existing library.
I'm tempted to say "write your own", which is what I have done. On the other hand, you might want to reuse what I wrote: test_util.hpp and test_util.cpp. It is straightforward to inline the one definition from the cpp file into the hpp file. MIT lisence. I have also pasted it into this answer, below.
This lets you write a test file like this:
#include "test_util.hpp"
bool test_one() {
bool ok = true;
CHECK_EQUAL(1, 1);
return ok;
}
int main() {
bool ok = true;
ok &= test_one();
// Alternatively, if you want better error reporting:
ok &= EXEC(test_one);
// ...
return ok ? 0 : 1;
}
Browse around in the tests directory for more inspiration.
// By Magnus Hoff, from http://stackoverflow.com/a/9964394
#ifndef TEST_UTIL_HPP
#define TEST_UTIL_HPP
#include <iostream>
// The error messages are formatted like GCC's error messages, to allow an IDE
// to pick them up as error messages.
#define REPORT(msg) \
std::cerr << __FILE__ << ':' << __LINE__ << ": error: " msg << std::endl;
#define CHECK_EQUAL(a, b) \
if ((a) != (b)) { \
REPORT( \
"Failed test: " #a " == " #b " " \
"(" << (a) << " != " << (b) << ')' \
) \
ok = false; \
}
static bool execute(bool(*f)(), const char* f_name) {
bool result = f();
if (!result) {
std::cerr << "Test failed: " << f_name << std::endl;
}
return result;
}
#define EXEC(f) execute(f, #f)
#endif // TEST_UTIL_HPP
Try google-test https://github.com/google/googletest/
it's really light weight, cross platform and simple.

Modify Code through a GUI

Hey this is more of a question, i want to know if it is possible to modify code through GUI asking because i was asked to see if i could create a GUI where the user can change certain attributes. i.e an exmaple is below
start %= -(status)
> lexeme[elementV]
> -(lexeme[elementF])
> +(inboundGroup);
Above is part of my code which is Boost SPIRIT which parses Strings so for example would it be possible to change the + to a * or - etc
+ = One
- = optional
* = multiple
Do you think it would be possible to change that through a GUI i think it could be just not sure on how to do it?
Any help i will be very grateful
Thanks Shamari
Everything is possible in programming ;-)
For dynamic modification of a program during execution, there are several solutions :
Use a dynamic language like LUA
Use a plugin system with dynamic loading
Since you require C++ and Boost Spirit, I think the best solution is to generate a plugin on the fly and load it afterwards.
Your program will generate code, compile it into a shared library (.so) and then load and execute it. (Some people will find that dirty. It's insecure also. But it's simple and it works.)
Here is an exemple for linux : plugin.h :
#ifndef PLUGIN_H__
#define PLUGIN_H__
#ifdef __cplusplus
extern "C" {
#endif
int process();
typedef int (*plugin_process_fn_ptr)();
#ifdef __cplusplus
}
#endif
#endif // PLUGIN_H__
Note that we must use extern C or else, C++ name mangling will make it difficult to import symbols.
plugin.cpp :
#include "plugin.h"
#include <iostream>
using namespace std;
int process()
{
int return_value = 0;
#include "plugin_content.inc.cpp"
return return_value;
}
Note that I use a hack here, the code will be included from another file, "plugin_content.inc.cpp". The code from user will be put inside.
a script to build the plugin, "build_plugin.sh" :
#! /bin/sh
g++ -c -Wall -fPIC plugin.cpp -o plugin.o
gcc -shared -o libplugin.so plugin.o
Now the calling program, main.cpp :
#include <iostream>
#include <fstream> // to open files
#include <dlfcn.h> // C lib to load dynamic libs
#include "plugin.h"
using namespace std;
// load the plugin and call the process() function fom it
static int process_via_plugin()
{
int return_value = -1;
void *lib_handle(NULL);
char *error(NULL);
char *plugin_lib = "./libplugin.so";
lib_handle = dlopen(plugin_lib, RTLD_LAZY);
if (!lib_handle)
{
cerr << "Error loading lib " << plugin_lib << " : " << dlerror() << endl;
exit(1);
}
char *plugin_fn = "process";
plugin_process_fn_ptr fn = (plugin_process_fn_ptr)dlsym(lib_handle, plugin_fn);
error = dlerror();
if (error)
{
cerr << "Error finding lib " << plugin_fn << " : " << error << endl;
exit(1);
}
// call the function loaded from lib
return_value = (*fn)();
dlclose(lib_handle);
lib_handle = NULL; // useless but for good habits ^^
return return_value;
}
// build or rebuild the plugin,
// we must call it when we change the plugin code code
static int build_plugin(string code)
{
{
char *plugin_code_file = "plugin_content.inc.cpp";
ofstream plugin_code(plugin_code_file, ios::out);
plugin_code << code << endl;
}
system("build_plugin.sh");
return 0;
}
// our program
int main(int argc, char *argv[])
{
cout << "Hello World !" << endl;
string code = ""
"cout << \"Hello from plugin !\" << endl;"
"";
// build a first version of the plugin and call it
build_plugin(code);
process_via_plugin();
// now we modify the code (use a GUI here)
code = ""
"cout << \"Hello from plugin, updated !\" << endl;"
"";
// rebuild the plugin and call it again
build_plugin(code);
process_via_plugin();
// do it again as much as you want.
return 0;
}
Now, build your program :
g++ -Wall -rdynamic -ldl main.cpp
and execute it :
a.out
and you get :
Hello World !
Hello from plugin !
Hello from plugin, updated !
The code I give you is very basic. For example, we should check if the compilation of the plugin is successful and report errors to the user. Now it's up to you to add more stuff.

C++ enable/disable debug messages of std::couts on the fly

Is there a way to define/undefine debug messages using std::cout whenever inside a program?
I am aware that there are such things such as #define, #ifndef, but I was thinking is there a cleaner way to having a variable say:
# debug ON
That prints all of my debug data (using std::cout). Consequently, we'll have code like this for debug:
#ifndef DEBUG
// do something useful
#endif
I find the above code cumbersome when you write 100s of debug code.
Thanks!
Carlo
#ifdef DEBUG
#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
#else
#define DEBUG_MSG(str) do { } while ( false )
#endif
int main()
{
DEBUG_MSG("Hello" << ' ' << "World!" << 1 );
return 0;
}
Some logging libraries are pretty heavy weight unless you have complex logging needs. Here's something I just knocked together. Needs a little testing but might meet your requirements:
#include <cstdio>
#include <cstdarg>
class CLog
{
public:
enum { All=0, Debug, Info, Warning, Error, Fatal, None };
static void Write(int nLevel, const char *szFormat, ...);
static void SetLevel(int nLevel);
protected:
static void CheckInit();
static void Init();
private:
CLog();
static bool m_bInitialised;
static int m_nLevel;
};
bool CLog::m_bInitialised;
int CLog::m_nLevel;
void CLog::Write(int nLevel, const char *szFormat, ...)
{
CheckInit();
if (nLevel >= m_nLevel)
{
va_list args;
va_start(args, szFormat);
vprintf(szFormat, args);
va_end(args);
}
}
void CLog::SetLevel(int nLevel)
{
m_nLevel = nLevel;
m_bInitialised = true;
}
void CLog::CheckInit()
{
if (!m_bInitialised)
{
Init();
}
}
void CLog::Init()
{
int nDfltLevel(CLog::All);
// Retrieve your level from an environment variable,
// registry entry or wherecer
SetLevel(nDfltLevel);
}
int main()
{
CLog::Write(CLog::Debug, "testing 1 2 3");
return 0;
}
Probably not. I would recommend using a logging library. I'm not sure what the best option is for C++ anymore, but I've used log4cpp in the past and found it pretty good.
EDIT: I assume on the fly means # runtime. If you just need it to be a compile time flag, then Gianni's answer is probably easiest to implement. Logging libraries give you a lot of flexibility and allow reconfiguration # runtime though.
Another simple solution, involves opening a std::ostream reference to cout in debug mode, and /dev/null in non-debug mode, like so:
In debug.h:
extern std::ostream &dout;
In debug.c
#ifdef DEBUG
std::ostream &dout = cout;
#else
std::ofstream dev_null("/dev/null");
std::ostream &dout = dev_null;
#endif
And then:
dout << "This is a debugging message";
Of course, this would only work on any system where /dev/null points to a null device. Since the dout reference is global here, it would much like cout. In this way, you can point the same stream to multiple output streams, for example to a log file, depending of the value of debug flags, etc.
Although the question is old, and there are some good answers, i want to post also a solution to this. It is like Giannis approach but different. And also, i used std::cerr instead of std::cout, but you can change this really quick.
#include <iostream>
#ifdef DEBUG
# define DEBUG_LOG std::cerr
#else
class log_disabled_output {};
static log_disabled_output log_disabled_output_instance;
template<typename T>
log_disabled_output& operator << (log_disabled_output& any, T const& thing) { return any; }
// std::endl simple, quick and dirty
log_disabled_output& operator << (log_disabled_output& any, std::ostream&(*)(std::ostream&)) { return any; }
# define DEBUG_LOG log_disabled_output_instance
#endif
int main() {
int x=0x12345678;
DEBUG_LOG << "my message " << x << " " << "\n more information" << std::endl;
};
Now you can use it just like a output stream.
(Note: iostream is only included if cerr is used. This will reduce the amount of inclusion if you don't have it already included. -edit: not with std::endl support).
If DEBUG is defined cerr is used to print the error. Otherwise the dummy class log_disabled_output is instantiated statically and operator<< is overloaded to any type. The vantage is; If you disable the logging, a clever compiler will notice that there is nothing to do with the stream and optimize the entire "line" away, so you don't have any overhead if DEBUG is disabled.
I was trying to do the same thing. After some research, I developed the following, and it seems to work. Please comment if you see anything wrong.
ostream DbgMsg(NULL);
enum {
DBGMSG_NONE,
DBGMSG_DEFAULT,
DBGMSG_VERBOSE
} DbgLvl = DBGMSG_DEFAULT;
ostream &DbgMsgDefault(ostream &stream) {
return (DbgLvl>=DBGMSG_DEFAULT) ? cout : stream;
}
ostream &DbgMsgVerbose(ostream &stream) {
return (DbgLvl>=DBGMSG_VERBOSE) ? cout : stream;
}
void main() {
DbgMsg<<DbgMsgDefault<<"default:default"<<endl;
DbgMsg<<DbgMsgVerbose<<"default:verbose"<<endl;
DbgLvl = DBGMSG_NONE;
DbgMsg<<DbgMsgDefault<<"none:default"<<endl;
}
A clean thing to do would be to use cerr.
"cerr" acts essentially as "cout", but always flushes the output (useful for debugging, by the way). If you need to remove all the messages, you can comment out all the cerr messages with a simple find-and-replace (cerr into //cerr).
There are probably even better ways to use cerr and to desactivate it cleanly (which writes into a special stream, the error stream, hence the name).
I hope this helps.
This is what I used (worked with VC++) - here "##" is used for concatennation
#ifdef DEBUG
#define pout cout
#else
#define pout / ## / cout
#endif
For other compilers use this :
#ifdef DEBUG
#define pout cout
#else
#define pout 0 && cout
#endif
Usage :
pout << "hello world" << endl;
I was looking for similar example and sharing my example below:
#include <iostream>
enum debug_option
{
DEBUG_DISABLE,
DEBUG_ENABLE
};
class debug
{
public:
debug_option debug_state;
debug() : debug_state(DEBUG_ENABLE) {} // constr
debug(debug_option state) : debug_state(state) {} // constr
template<typename T>
debug & operator<< (T input)
{
if (this->debug_state == DEBUG_ENABLE)
std::cout << input;
return *this;
}
};
int main()
{
debug log, log_lev2(DEBUG_DISABLE);
log << "print 1..\n" << 55 << " over\n";
log.debug_state = DEBUG_DISABLE;
log << "print 2..\n" << 3 << "over\n";
log_lev2 << "print 3..\n" << 4 << "over\n";
log_lev2.debug_state = DEBUG_ENABLE;
log_lev2 << "print 5..\n";
std::cout << "std::cout << print..\n";
return 0;
}
Better suggestions are always welcome.