Any portable tricks to obtain namespace name in C++? - c++

I have some well-formed code looks like this:
NAMESPACE_BEGIN(Foo)
inline void test() {
string s = xxx;
}
NAMESPACE_END(Foo)
So, is there any portable tricks by using the NAMESPACE_BEGIN() macro to obtain namespace name "Foo" in test()?
I'm thinking of something like this, but it would surely cause symbol redefinition:
#define NAMESPACE_BEGIN(x) \
namespace x { \
inline const char *_curNamespace() { \
return #x; \
}
#define NAMESPACE_END(x) \
}
There's also a workaround looks like this, but that's not very convenient
#define NAMESPACE_NAME Foo
// using a header file so that we can use #ifdef guard
#include "MyNamespaceBegin.h"
...
#include "MyNamespaceEnd.h"
EDIT:
Why I need this:
I'm using much of macro to generate codes to achieve some
dynamic reflection logic (yes, not static template reflection),
it's all right within class scope by using static member function,
but does not work for namespaces
Why not to manually declare the name getter once:
What I want is something like this:
// the global default version
const char *_curNamespace() {return "";}
namespace X {
// the local namespace version
const char *_curNamespace() {return "X";}
// some verbose reflection register code
...
registerSomething(_curNamespace());
...
}
Of course, all of the verbose register code should be generated by macro
And, app level user should not care about the _curNamespace(),
so, I want to simplify the user's usage,
by using a custom NAMESPACE_BEGIN(xxx) macro at any case
If you are still curious about what I'm doing,
check this: https://github.com/ZFFramework/ZFFramework
I'm using lots of tricks to achieve fully dynamic reflection in pure C++,
to achieve some of my fancy thoughts,
for now, this project is just for fun,
I have no idea whether it has practicability
EDIT2:
For now, I think the best workaround should be like this:
#define NAMESPACE_BEGIN(ns) \
namespace ns { \
extern const char *__curNS();
#define NAMESPACE_END(ns) \
}
#define NAMESPACE_REG(ns) \
const char *__curNS() {return #ns;}
app level users still only need to care about NAMESPACE_BEGIN
NAMESPACE_REG must be declared exactly once, in source file
if not, undefined symbol would happen
if more than once, duplicated symbol would happen
although it's annoying and sometimes you need additional source file
to hold the NAMESPACE_REG,
the strict rule should prevent user from forgetting the ugly workaround

You are making much fuss over something that is trivial to implement.
First of all, use of NAMESPACE_BEGIN and NAMESPACE_END seems unnecessary to me. I don't see how that is more readable or useful than
namespace Foo
{
}
If getting the name of the namespace is important/useful, add a trivial function.
namespace Foo
{
inline std::string get_name() { return "Foo"; }
}
Small sized real world applications need thousands of lines of code. Large sized real world applications need millions of lines of code. From that perspective, implementing a one line inline function is a very minor task.

This solution employs a bit of preprocessor magic and has these features:
Namespace is mentioned only once
Access to a macro containing the unquoted name
Access to a macro containing the quoted name
Support for repeating the same namespace
Support for different namespaces
Misuse of the BEGIN/END macros is detected
Cleanup, i.e. no extra macros defined outside the BEGIN/END block
It does not support nested namespaces.
Example of usage:
#include "framework.hpp"
#define NAMESPACE_NAME Foo
#include NAMESPACE_BEGIN
// Here you have access to NAMESPACE_NAME (unquoted, i.e. Foo)
// and also to NAMESPACE_NAME_STRING (quoted, i.e. "Foo")
#include NAMESPACE_END
// NAMESPACE_NAME and NAMESPACE_NAME_STRING do not exist
// outside the block, so they cannot be misused
// Different namespaces in the same TU are supported
#define NAMESPACE_NAME Bar
#include NAMESPACE_BEGIN
inline std::string f()
{
return NAMESPACE_NAME_STRING;
}
#include NAMESPACE_END
// Repeating the same namespace is also supported
#define NAMESPACE_NAME Foo
#include NAMESPACE_BEGIN
inline std::string f()
{
return NAMESPACE_NAME_STRING;
}
#include NAMESPACE_END
The implementation follows:
framework.hpp
#pragma once
#define NAMESPACE_BEGIN "framework_namespace_begin.hpp"
#define NAMESPACE_END "framework_namespace_end.hpp"
framework_namespace_begin.hpp
#ifndef NAMESPACE_NAME
#error "NAMESPACE_NAME not defined"
#endif
#define NAMESPACE_IN_NAMESPACE 1
#define NAMESPACE_NAME_DO_STR(X) #X
#define NAMESPACE_NAME_STR(X) NAMESPACE_NAME_DO_STR(X)
#define NAMESPACE_NAME_STRING NAMESPACE_NAME_STR(NAMESPACE_NAME)
namespace NAMESPACE_NAME {
framework_namespace_end.hpp
#ifndef NAMESPACE_IN_NAMESPACE
#error "NAMESPACE_IN_NAMESPACE not defined"
#endif
}
#undef NAMESPACE_NAME
#undef NAMESPACE_NAME_STRING
#undef NAMESPACE_IN_NAMESPACE

You know what? I think I might just have a viable solution for this. It's actually very simple, and it's very close to the OP's original suggestion (which really only had the problem of a potential duplicate definition if you wanted to open the namespace twice in the same translation unit). You just have to think a bit laterally and not be too precious about seeing your namespaces being bracketed by macros instead of curly braces.
So let me just lay it out here, because there's really nothing to it, and then I'll explain why I personally happen to like it.
Code:
Macros:
#define DECLARE_NAMESPACE(ns) \
namespace ns {\
static constexpr const char *_curNamespace = #ns; \
}
#define BEGIN_NAMESPACE(ns) \
namespace ns { \
static_assert (ns::_curNamespace, "BEGIN_NAMESPACE: namespace has not been declared");
#define END_NAMESPACE }
Sample code:
#include <iostream>
DECLARE_NAMESPACE (Foo)
BEGIN_NAMESPACE (Foo)
void print_namespace_name () { std::cout << _curNamespace << "\n"; }
END_NAMESPACE
BEGIN_NAMESPACE (Foo)
void another_print_namespace_name () { std::cout << _curNamespace << "\n"; }
END_NAMESPACE
DECLARE_NAMESPACE (Bar)
BEGIN_NAMESPACE (Bar)
void print_namespace_name () { std::cout << _curNamespace << "\n"; }
DECLARE_NAMESPACE (BarBar)
BEGIN_NAMESPACE (BarBar)
void print_namespace_name () { std::cout << _curNamespace << "\n"; }
END_NAMESPACE
END_NAMESPACE
int main ()
{
Foo::print_namespace_name ();
Foo::another_print_namespace_name ();
Bar::print_namespace_name ();
Bar::BarBar::print_namespace_name ();
}
Output:
Foo
Foo
Bar
BarBar
Now this is obviously very straightforward to implement and also easy to use and has no obvious limitations. In particular, it can handle nested namespaces (as shown in the code above) and opening a namespace twice in the same compilation unit also works (again, this is shown in the code snippet).
But, but, but, don't we still have to type in the name of the namespace twice, and wasn't that the very thing we were trying to avoid to eliminate typos?
Well, sure, we have to type the name in twice, but so what, live with it. Point is, with this particular set of macros, the compiler will now catch any typos for us. Let's prove that by deliberately putting one in. So this:
DECLARE_NAMESPACE Whoops
BEGIN_NAMESPACE whoops
END_NAMESPACE
Generates this (I couldn't find a better way of formulating the static_assert, sorry):
prog.cc:12:24: error: '_curNamespace' is not a member of 'whoops'
static_assert (ns::_curNamespace, "BEGIN_NAMESPACE: namespace has not been declared");
^~~~~~~~~~~~~
prog.cc:27:5: note: in expansion of macro 'BEGIN_NAMESPACE'
BEGIN_NAMESPACE (whoops)
^~~~~~~~~~~~~~~
And more importantly this (and this is why we need the BEGIN_NAMESPACE macro):
DECLARE_NAMESPACE (Bar)
BEGIN_NAMESPACE (Bar)
DECLARE_NAMESPACE (BarWhoops)
BEGIN_NAMESPACE (Barwhoops)
END_NAMESPACE
END_NAMESPACE
Generates this:
prog.cc:12:24: error: '_curNamespace' is not a member of 'Bar::Barwhoops'
static_assert (ns::_curNamespace, "BEGIN_NAMESPACE: namespace has not been declared");
^~~~~~~~~~~~~
prog.cc:42:5: note: in expansion of macro 'BEGIN_NAMESPACE'
BEGIN_NAMESPACE (Barwhoops)
^~~~~~~~~~~~~~~
Which is just dandy.
So, you know, what's not to like?
Live demo - uncomment line 3 to see those compiler errors.

you can use a variable and change its value with 'NAMESPACE_BEGIN' and 'NAMESPACE_END'
the variable __name represent the current full namespace position
like "abc::def::detail"
std::string __name = "";
std::string & __append(std::string & str, const char * ptr) {
if (!str.empty()) {
str.append("::");
}
str.append(ptr);
return str;
}
std::string & __substr(std::string & str, const char * ptr) {
if (str.length() == strlen(ptr)) {
str.clear();
} else {
str = str.substr(0, str.length() - strlen(ptr) - 2);
}
return str;
}
#define NAMESPACE_NAME __name
#define CONCATENATE_DIRECT(s1, s2) s1##s2
#define CONCATENATE(s1, s2) CONCATENATE_DIRECT(s1, s2)
#ifdef _MSC_VER
# define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __COUNTER__)
#else
# define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__)
#endif
#define APPEND_NAME(x) std::string ANONYMOUS_VARIABLE(__start_name) = __append(__name, #x)
#define SUBSTR_NAME(x) std::string ANONYMOUS_VARIABLE(__end_name) = __substr(__name, #x)
#define NAMESPACE_BEGIN(x) \
namespace x { \
APPEND_NAME(x);
#define NAMESPACE_END(x) \
SUBSTR_NAME(x); \
}
then you can use the NAMESPACE_NAME macro for the full name or you can extract the last name from it

Here's a way. The core idea came from the line of thought:
Q: How can I define multiple things with the same name accessible from the same scope?
A: Make them all functions with different parameter types. And if all of them have identical bodies, it doesn't matter which one gets called.
Q: How can I generate an unlimited set of different parameter types?
A: A class template.
Q: How can I make sure a call to that set of overloaded functions will never be ambiguous?
A: Make sure the binary relation "is implicitly convertible from" is a complete ordering on the parameter types, and use a unique minimal element for the argument type.
#include <type_traits>
#include <functional>
struct NamespaceHandleObj {
template <const NamespaceHandleObj* Handle1, const NamespaceHandleObj* Handle2>
struct less : public std::bool_constant<std::less<>{}(Handle1, Handle2)> {};
};
template <>
struct NamespaceHandleObj::less<nullptr, nullptr> : public std::false_type {};
template <const NamespaceHandleObj* Handle1>
struct NamespaceHandleObj::less<Handle1, nullptr> : public std::false_type {};
template <const NamespaceHandleObj* Handle2>
struct NamespaceHandleObj::less<nullptr, Handle2> : public std::true_type {};
template <const NamespaceHandleObj* Handle>
struct NamespaceParamType
{
constexpr NamespaceParamType() noexcept = default;
template <const NamespaceHandleObj* Other,
typename = std::enable_if_t<NamespaceHandleObj::less<Other, Handle>::value>>
constexpr NamespaceParamType(NamespaceParamType<Other>) noexcept {}
};
#define NAMESPACE_UTILS_TOSTR1(x) #x
#define NAMESPACE_UTILS_TOSTR(x) NAMESPACE_UTILS_TOSTR1(x)
#define BEGIN_NAMESPACE(ns) \
namespace ns { \
namespace { \
constexpr NamespaceHandleObj namespace_handle_{}; \
constexpr const char* current_ns_(
NamespaceParamType<&namespace_handle_>) noexcept \
{ return NAMESPACE_UTILS_TOSTR(ns); } \
}
#define END_NAMESPACE }
#define CURRENT_NAMESPACE (current_ns_(NamespaceParamType<nullptr>{}))
The code above is C++17, but it wouldn't be hard to port it to previous versions, even all the way to C++03.

Related

Best way to deal with a trailing comma when using X macros in C++

What's the best way to deal with extra trailing commas when working with X macros? Specifically, I have the following setup in a file test01.cpp
struct Foo {
#define X(name,val) int name;
#include "test01.def"
#undef X
Foo() :
#define X(name,val) name(val),
#include "test01.def"
#undef X
{}
};
int main(){
Foo foo;
}
In test01.def, I have
X(foo,1)
X(bar,23)
This doesn't compile because of the error
test01.cpp: In constructor 'Foo::Foo()':
test01.cpp:10:5: error: expected identifier before '{' token
{}
Basically, there's a trailing comma after the last element in the member initializer list. Now, we can fix this by adding a dummy variable:
struct Foo {
private:
void * end;
public:
#define X(name,val) int name;
#include "test01.def"
#undef X
Foo() :
#define X(name,val) name(val),
#include "test01.def"
#undef X
end(nullptr)
{}
};
int main(){
Foo foo;
}
However, this is sort of ugly. As such, is there a better way to handle the trailing comma in the member initializer list?
Edit 1
Here's another option that's still kind of ugly:
struct Foo {
#define X(name,val) int name;
#include "test01.def"
#undef X
Foo() :
#define X(name,val) name(val),
#define XLAST(name,val) name(val)
#include "test01.def"
#undef XLAST
#undef X
{}
};
int main(){
Foo foo;
}
along with
#ifndef XLAST
#define XLAST X
#define CLEANUP
#endif
X(foo,1)
XLAST(bar,23)
#ifdef CLEANUP
#undef XLAST
#undef CLEANUP
#endif
Basically, we define the macro XLAST to take care of the final comma. If we use XLAST, we have to manually undefine it like X, but we do this automatically in the case that we don't define it explicitely.
Since you've tagged this C++14, the easiest way to solve this problem is to use brace-or-equal-initializers instead of the mem-initializers.
struct Foo {
#define X(name,val) int name = val;
#include "test01.def"
#undef X
// Foo() {} // uncomment if you do not want Foo to be an aggregate
};
If you want to stick with a preprocessor solution, you can use Boost.Preprocessor to do this. You'll need to change the format of your data member definitions so it forms a sequence.
#define FOO_MEMBERS ((int,i,10)) ((long,j,20))
I added the ability to specify arbitrary data types too.
First let's declare and initialize these data members
struct Foo
{
#define OP(s, data, elem) BOOST_PP_TUPLE_ELEM(3, 0, elem) \
BOOST_PP_TUPLE_ELEM(3, 1, elem) = \
BOOST_PP_TUPLE_ELEM(3, 2, elem);
BOOST_PP_SEQ_FOR_EACH(OP, , FOO_MEMBERS)
// expands to
// int i = 10; long j = 20;
#undef OP
Foo() = default; // default constructor
};
BOOST_PP_SEQ_FOR_EACH will expand the macro OP for each element in the sequence FOO_MEMBERS.
BOOST_PP_TUPLE_ELEM simply extracts a single element from its tuple argument.
Next, let's give Foo a constructor that takes arguments corresponding to each data member and initializes it.
#define OP(s, data, elem) (BOOST_PP_TUPLE_ELEM(3, 0, elem) BOOST_PP_TUPLE_ELEM(3, 1, elem))
Foo(
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(OP, , FOO_MEMBERS))
// expands to
// int i, long j
) :
#undef OP
#define OP(s, data, elem) (BOOST_PP_TUPLE_ELEM(3, 1, elem)(BOOST_PP_TUPLE_ELEM(3, 1, elem)))
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(OP, , FOO_MEMBERS))
// expands to
// i(i), j(j)
#undef OP
{}
We use BOOST_PP_SEQ_ENUM to generate a comma separated list from the result of the expansion of BOOST_PP_SEQ_FOR_EACH.
Live demo
If you declare end to be of std::nullptr_t type the compiler is likely to optimize it and remove it. And the intent is clear to the reader.
struct Foo {
private:
static std::nullptr_t end;
alternatively, you might declare char end[0]; (this won't use any space) but some compilers might reject that.
Of course, as Pratorian answered, you could use some X-macro friendly construct instead.
For anybody looking for a solution not involving a dependency on BOOST_PP, a preprocessor-based alternative, also useful for plain-old C, is to deal with a leading comma using the preprocessor, which is much easier than dealing with a trailing comma.
/// Indirection macro, so that macro expansion of parameters is done before token pasting.
#define REMOVE_FIRST(...) REMOVE_FIRST_SUB(__VA_ARGS__)
/// Paste all parameters but first.
#define REMOVE_FIRST_SUB(X, ...) __VA_ARGS__
#define FOO_DEF(X) \
X(foo,1) \
X(bar,23)
struct Foo {
#define X(name,val) int name;
FOO_DEF(X)
#undef X
Foo() :
#define X(name,val) ,name(val)
REMOVE_FIRST(FOO_DEF(X))
#undef X
{}
};
int main(){
Foo foo;
}
Testing:
$ gcc -E test.c
# 0 "test.c"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "test.c"
# 11 "test.c"
struct Foo {
int foo; int bar;
Foo() :
foo(1) ,bar(23)
{}
};
int main(){
Foo foo;
}

conditional derivative usage of macro in cpp

I have a question. In one of my projects i am using the FLAG PRINT to enable/disable the debug printfs. currently I am using something like this.
#ifdef PRINT
printf("DEBUG");
#endif
It is a pain to put this #ifdef before every printf. So I was thinking to 've a #define for the #ifdef, something like
#define DEBUG_PRINT
#define PRINT (#ifdef DEBUG_PRINT)
#define ENDPRINT #endif
so that I can use like
PRINT
printf("DEBUG");
ENDPRINT
but it is giving a compiler error. Can you tell me someway to simplify.
Thanks,
A standard way is
#ifdef DEBUG_PRINT
# define is_debug() (1)
#else
# define is_debug() (0)
#endif
#define pr_dbg(fmt, ...) do { \
if (is_debug()) \
printf(fmt, __VA_ARGS__); \
} while (0)
When using gcc, you can/should write
printf(fmt, ## __VA_ARGS__);
to deal with empty args.
In your code you can write then
pr_dbg("foo=%u\n", foo);
Optimizer will throw away the expression when DEBUG_PRINT is not defined but your debug statements will be still checked for syntax errors. This avoids silent breakage when e.g. undefined variables are used within an #ifdef clause.
How about a header with
#ifdef DEBUG
#define ON_DEBUG(X,...) do { X, __VA_ARGS__; } while( false )
#else
#define ON_DEBUG(X,...) do {} while( false )
#endif
and in your code, you simply use
ON_DEBUG( printf("Hallo, %s", "Welt") );
(the do-while forces you to add the final semicolon and protects the statement's in cases if (nested) if-statements, see Aaron McDaid's comment)
I would actually do it a different way entirely. First define the flag that turns printing on or off:
// uncomment to turn off debug printing
#define DEBUG_PRINT 1
Then conditionally define your printer macro depending of the definition state of DEBUG_PRINT:
#ifdef DEBUG_PRINT
#define PRINT (X) (printf(x))
#else
#define PRINT (x)
#endif
Which can be used simply as:
PRINT("foo");
But in reality, I wouldn't do any of this stuff at all. Instead, I'd have the turn-on/turn-off flag as above, and then build a class that does the printing:
// comment out to not do debug printing
//#define DEBUG_PRINTING 1
#ifdef DEBUG_PRINTING
class Printer
{
public:
Printer() {}
~Printer()
{
std::cout << mOutput.str() << "\n";
}
template <typename TYPE> Printer& operator<< (const TYPE& val)
{
mOutput << val;
return * this;
}
template <size_t N> Printer& operator<< (const char(&ary)[N])
{
mOutput << ary;
return * this;
}
private:
std::stringstream mOutput;
};
#else
class Printer
{
public:
Printer() {};
template <typename TYPE> Printer& operator<< (const TYPE& val)
{
return * this;
}
template <size_t N> Printer& operator<< (const char(&ary)[N])
{
return * this;
}
};
#endif
int main()
{
Printer() << "My output here. " << 42;
}
In optimized builds where the flag is not defined, most (if not all) of the code will be optimized away.

Can #define preprocessor directive contain if and else?

I was trying the logger code from this link, but it gives me error. How to implement a good debug/logging feature in a project
#ifndef _LOGGER_HPP_
#define _LOGGER_HPP_
#include <iostream>
#include <sstream>
/* consider adding boost thread id since we'll want to know whose writting and
* won't want to repeat it for every single call */
/* consider adding policy class to allow users to redirect logging to specific
* files via the command line
*/
enum loglevel_e
{logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4};
class logIt
{
public:
logIt(loglevel_e _loglevel = logERROR) {
_buffer << _loglevel << " :"
<< std::string(
_loglevel > logDEBUG
? (_loglevel - logDEBUG) * 4
: 1
, ' ');
}
template <typename T>
logIt & operator<<(T const & value)
{
_buffer << value;
return *this;
}
~logIt()
{
_buffer << std::endl;
// This is atomic according to the POSIX standard
// http://www.gnu.org/s/libc/manual/html_node/Streams-and-Threads.html
std::cerr << _buffer.str();
}
private:
std::ostringstream _buffer;
};
extern loglevel_e loglevel;
#define log(level) \
if (level > loglevel) ; \
else logIt(level)
#endif
More precisely, this #define is giving errors:
#define log(level) \
if (level > loglevel) ; \
else logIt(level)
The errors are Syntax error: if and Syntax error: else
But later, I noticed that if I move #include "logger.hpp" from main.h to main.cpp, the problem disappeared. Though 'main.h' is included many times in different places, it does contain '#pragma once'.
Any idea?
If loglevel is known at compile time you can do the following:
template <bool>
struct LogSystem
{
template <class T>
LogSystem& operator << (const T &)
{
//ignore the input
return (*this);
}
};
template <>
struct LogSystem <true>
{
template <class T>
LogSystem& operator << (const T & v)
{
cout << v;
return (*this);
}
};
template <bool B>
LogSystem<B> getLog()
{
return LogSystem<B>();
}
#define log(level) getLog< (level <= loglevel) >()
if loglevel is not known at compile time:
class iLogSystem
{
public:
virtual iLogSystem& operator << (const int &)
{
//empty
return (*this);
}
virtual iLogSystem& operator << (const custom_type &);
{
return (*this);
}
//make functions for logging all the types you want
};
class LogSystem : public iLogSystem
{
public:
virtual iLogSystem& operator << (const int & v)
{
cout << v;
return (*this);
}
virtual iLogSystem& operator << (const custom_type & q);
{
cout << q.toString();
return (*this);
}
//make functions for logging all the types you want
};
iLogSystem& getLog(const bool l)
{
static LogSystem actual_log;
static iLogSystem empty_log;
if(l)
return &actual_log;
return &empty_log;
}
#define log(level) getLog( level <= loglevel )
Any time you want to define a macro that expands to a statement, if the definition contains any compound statements (including if/else), you should wrap the definition in do ... while (0). The enclosed code will still execute exactly once, and it can be used in any context that requires a statement.
That's the only way I know of to avoid syntax errors when the macro is used within an if/else statement, due to the use of semicolons.
So rather that this:
#define log(level) \
if ((level) > loglevel) ; \
else logIt(level)
you can use this:
#define log(level) \
do { \
if ((level) > loglevel) ; \
else logIt(level) \
} while (0)
I've added parentheses around references to the macro's level parameter, to avoid any possible operator precedence problems. Note also the lack of a semicolon at the end; the semicolon will be supplied by the caller.
On the other hand, an if/else can often be replaced by the conditional (ternary) ?: operator:
#define log(level) \
((level) > loglevel ? 0 : logIt(level))
which allows log(level) to be used anywhere an expression can be used; that includes statement context if you add a semicolon. You might want to replace 0 by something of the type returned by logIt; if logIt is a void function, you might want:
#define log(level) \
((level) > loglevel ? (void)0 : logIt(level))
This all assumes that a macro is the right tool for the job. It's likely that a template (as suggested by this answer) or an inline function will do the job better and with less potential for confusion.
Can #define preprocessor directive contain if and else?
Yes.
Regarding your problem: preprocessor is dumb as a rock and performs only simple text subsitution. It is not a function, it is not a language construct, it is simple, dumb text subsitution. As a a result, this:
#define log(level) \
if (level > loglevel) ; \
else logIt(level)
...
log(logINFO) << "foo " << "bar " << "baz";
Turns into this:
if (logINFO > loglevel); // << here's your problem.
else
logIt(logInfo)
<< "foo " << "bar " << "baz";
Your problem is;. Here, semicolon indicates end of c++ if statement, so when compiler encounters else afterwards, it doesn't know what to do with it.
I noticed that if I move #include "logger.hpp" from main.h to main.cpp, the problem disappeared
C++ has "logarithm" function. Which is called log. If your other files use logarithm function, things will get very interesting, because it'll be replaced by your if/else logging code everywhere.
For example, if there's inlined logarithm code somewhere in a header, it'll turn into nonsense if you include your logger header first. For example log(6.0) + 1 will turn into log (if (6.0 > logLevel); else logIt(6.0)) + 1, which is not a valid C++ statement.

Ignore code between two C++ macros (prevent creating static unittest objects)

// in someFile.h or someFile.cpp
TEST()
{
"example test", []
{
EXPECT(0 == 1);
}
}
TEST_END()
// in main.cpp
int main() { ssvu::Test::runAllTests(); }
#define TEST() static RunOnCtor UNIQUENAME(__LINE__) { []{ getStaticTests().push_back({
#define TEST_END() });}};
struct RunOnCtor { RunOnCtor(std::function<void()> f) { f(); } };
I've created some unit testing macros that work both in header (useful for my header-only libraries) and source files.
TEST() creates a static instance of RunOnCtor, which, on construction, executes a lambda which inserts the test lambda into a std::vector of tests. runAllTests() runs every test in that vector.
I have created a DISABLE_TEST define that simply puts return; at the beginning of the RunOnCtor lambda, so that no tests are added to the internal vector. However, I would like to prevent unnecessary construction of static objects when tests are disabled.
Is there a way to completely ignore everything between TEST() and TEST_END()? Something like commenting it out. Or would emptying out RunOnCtor (empty struct) make the compiler avoid static constructions?
I think this should work:
#define TEST() struct UNIQUENAME(__LINE__) { void f() {
#define TEST_END() } };
The following is based on #Angew 's answer but uses standard preprocessor definitions. The class then defines a function within the class declaration, which in C++ forces it to be inline. Because the class is never instantiated and the function is never called, no code is ever generated.
#define CAT(a, ...) PCAT(a, __VA_ARGS__)
#define PCAT(a, ...) a ## __VA_ARGS__
#define TEST() class CAT(Obfuscate_, __LINE__) { void f() {
#define TEST_END() } };
int c;
TEST()
int a = 7;
int b = a * 17;
c = b + 4;
return;
TEST_END()
Here's Godbolt's handy-dandy compiler explorer to prove that GCC, CLANG, and ICC produce no code for the above: https://godbolt.org/g/BXKDNF

Elegantly reuse code adding const to a class instantiation

I need to compile the same code with two different libraries. One allows the objects to be const, the other doesn't. The solution that's implemented now looks like this:
#ifdef (OLDLIB)
ClassFoo TheFoo = Bar();
#else
const ClassFoo TheFoo = Bar();
#endif
This is used many times for different classes and impedes readability. I'd like to make the distinction somewhere else.
I guess one could say:
#ifdef (OLDLIB)
#define CLASS_FOO ClassFoo
#define CLASS_BAR ClassBar
#else
#define CLASS_FOO const ClassFoo
#define CLASS_BAR const ClassBar
#endif
CLASS_FOO TheFoo = Bar();
CLASS_BAR TheBar = FooBar();
But I dislike preprocessor stuff. Is there a nice C++-Way of doing the above? Thanks.
Update 1:
As Peter Wood said, it is possible to just instantiate them non-const. I changed the sentence.
You can use std::conditional to select between two types based on a compile-time variable:
#ifdef OLDLIB
constexpr bool OLD = true;
#else
constexpr bool OLD = false;
#endif
std::conditional<OLD, ClassFoo, const ClassFoo>::type theFoo;
~~~ ~~~~~~~~ ~~~~~~~~~~~~~~
true false
Since C++11
I'm pretty sure you're stuck with the preprocessor to accomplish your goal.
However, I'd probably write it like this:
#ifdef OLDLIB
# define LIB_CONST
#else
# define LIB_CONST const
LIB_CONST ClassFoo TheFoo(Bar());
Either way is not super elegant but doing it this way at least means that you're only tweaking an object attribute via the preprocessor rather than the whole object declaration.
The easiest solution seems to be to just use non-const objects and let the compiler automatically add const where the new interface expects it.
Alternately could you use a typedef inside the proprocessor block?
#ifdef (OLDLIB)
typedef ClassFoo InstantiableFoo;
#else
typedef const ClassFoo InstantiableFoo;
#endif
You can typedef
// oldlib.h
typedef ClassFoo Foo;
typedef ClassBar Bar;
// newlib.h
typedef const ClassFoo Foo;
typedef const ClassBar Bar;
// the library's user
#include "oldlib.h" // or include "which_lib.h" that includes
// one of oldlib.h newlib.h
#include "your_library_that_uses_the_typedefs.h"
Foo TheFoo = Bar();
Bar TheBar = FooBar();
You can parametrize your library's classes and global functions
// library.h
template <class Foo>
class SomeClass { }
template <class Foo>
Foo makeFoo() { }
// library_user.cpp
#include "library.h"
SomeClass<const ClassFoo> sc;
sc.method();
const ClassFoo f = makeFoo();
You can even hide the type Foo inside of the external libraries
// external_library.h
class ExternalLibrary {
typedef const Foo foo_type;
};
ExternalLibrary::foo_type& foo_identity(const ExternalLibrary::foo_type &v) { return v; }
// your_library.h
ExternalLibrary::foo_type makeFoo() { }
foo_identity(f1);