I'd like to write a header that lets me declare preferences with a syntax similar to:
declpref("some.pref.name", "description");
Which registers some.pref.name with the given description with some global registry so I can easily introspect what preferences my code has declared, set their values from various sources, etc.
I'd probably do this with some sort of static-construction before main magic:
#define declpref(name, desc) \
{ \
static struct __pref { \
__pref() { \
register_preference(name, desc); \
} \
} __static_pref; \
}
The problem being that the above code wouldn't work the way I want it to if used in a local scope:
void some_function() {
declpref("some.pref", "description"); // won't register until some_function called
}
I think that I'm OK with forcing preference declarations to be done at global/namespace scope since they're supposed to be a globally unique name anyways.
How can I check the scope that its being declared in and throw an error though?
I am trying to define a macro that behaves differently when used in a function context vs a class body or namespace. The purpose of this is to selectively include BOOST_LOG_NAMED_SCOPE (or achieve equivalent behavior) in the LOG_CONTEXT macro referenced here.
I have tried two approaches:
Using BOOST_PP_IF along with a preprocessor function to test whether e.g. __func__ is non-empty.
The output of g++ -E on a basic source file still contains the literal text __func__ in both global and function scope so that probably rules out any approach targeting the preprocessing phase.
Using something like sizeof(__func__) to select a specialized template that implements behavior similar to BOOST_LOG_NAMED_SCOPE. I can re-use the boost::log::attributes::named_scope::sentry object from boost log, but I'm stuck trying to figure out how to instantiate it conditionally in a function context, or at least in a way that works everywhere. The following construction seems to work fine in class definitions and functions, but fails with a "multiple definition" error when linking together multiple translation units that include a header with a LOG_CONTEXT at global or namespace scope:
#include <boost/log/attributes/named_scope.hpp>
#include <type_traits>
namespace logging {
namespace attrs = boost::log::attributes;
namespace detail {
// Default no-op on construction when not in a function.
template<typename ScopeTraits, bool InFunction>
class named_scope_helper
{};
// Specialization when in a function.
template<typename ScopeTraits>
class named_scope_helper<ScopeTraits, true> :
public attrs::named_scope::sentry
{
public:
named_scope_helper() BOOST_NOEXCEPT
: sentry(
ScopeTraits::scope_name(),
ScopeTraits::filename(),
ScopeTraits::lineno() )
{}
};
template<size_t N>
class not_1 : public std::true_type
{};
template<>
class not_1<1> : public std::false_type
{};
#define LOGGING_LOG_IN_FUNCTION \
::logging::detail::not_1<sizeof(__func__)>::value
} // namespace detail
} // namespace logging
// scope_name_t/filename_t are required since attrs::named_scope::sentry
// requires string literals.
#define LOG_CONTEXT( name_ ) \
struct __logging_log_scope_traits__ \
{ \
using scope_name_t = const char (&)[sizeof(name_)]; \
static scope_name_t scope_name() \
{ return name_; } \
using filename_t = const char (&)[sizeof(__FILE__)]; \
static filename_t filename() \
{ return __FILE__; } \
static size_t lineno() \
{ return __LINE__; } \
}; \
::logging::detail::named_scope_helper< \
__logging_log_scope_traits__, LOGGING_LOG_IN_FUNCTION> \
BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_log_named_scope_sentry_);
My normal workaround for this would be to use static in the declaration of the _log_named_scope_sentry_, but that defeats the purpose.
I could add another macro that is strictly for non-execution contexts, but wanted to investigate this approach first since it would be an interesting trick to have. How can I proceed on one of the two approaches I've started above, or is there another option I haven't considered?
A general solution would be preferred but I'm only really concerned with GCC and Clang.
The simplest way of defining my problem is that I'm trying to implement a mechanism that would check whether the same string had already been used (or a pair (number, string)). I would like this mechanism to be implemented in a smart way using C preprocessor. I would also like that this mechanism gave me compile errors when there is a conflict or run-time errors in Debug mode (by checking assertions). We don't want the developer to make a mistake when adding a message, as every message should be unique. I know that it could be done by calculating a hash or for example crc/md5 but this mechanism would be conflict-vulnerable which I need to avoid. It is crucial that every message can be used only once.
Example behaviour of this mechanism:
addMessage(1, "Message1") //OK
addMessage(2, "Message2") //OK
.
.
.
addMessage(N, "MessageN") //OK
addMessage(2, "Message2") //Compile error, Message2 has already been used
Alternative behaviour (when Debugging code):
addMessage(1, "Message1") //OK
addMessage(2, "Message2") //OK
.
.
.
addMessage(N, "MessageN") //OK
addMessage(2, "Message2") //Assertion failed, because Message2 has already been used
The preferred way of doing it would be smart usage of #define and #undef directives. In general the preprocessor should be used in a smart way (I am not sure if this is possible) maybe it can be achieved by appropriate combinations of macros? Any C preprocessor hacker that could help me solve this problem?
//EDIT: I need those messages to be unique globally, not only inside one code block (like function of if-statement).
//EDIT2: The best description of the problem would be that I have 100 different source files and I would like to check with a preprocessor (or possibly other mechanism other than parsing source files with a script at a start of the compilation every-time, which would be very time-consuming and would add another stage to an enough complicated project) if a string (or a preprocessor definition) was used more than one time. I still have no idea how to do it (I know it may not be possible at all but I hope it actually is).
This will give an error on duplicate strings:
constexpr bool isequal(char const *one, char const *two) {
return (*one && *two) ? (*one == *two && isequal(one + 1, two + 1))
: (!*one && !*two);
}
constexpr bool isunique(const char *test, const char* const* list)
{
return *list == 0 || !isequal(test, *list) && isunique(test, list + 1);
}
constexpr int no_duplicates(const char* const* list, int idx)
{
return *list == 0 ? -1 : (isunique(*list, list + 1) ? no_duplicates(list + 1, idx + 1) : idx);
}
template <int V1, int V2> struct assert_equality
{
static const char not_equal_warning = V1 + V2 + 1000;
};
template <int V> struct assert_equality<V, V>
{
static const bool not_equal_warning = 0;
};
constexpr const char* l[] = {"aa", "bb", "aa", 0};
static_assert(assert_equality<no_duplicates(l, 0), -1>::not_equal_warning == 0, "duplicates found");
Output from g++:
g++ -std=c++11 unique.cpp
unique.cpp: In instantiation of ‘const char assert_equality<0, -1>::not_equal_warning’:
unique.cpp:29:57: required from here
unique.cpp:20:53: warning: overflow in implicit constant conversion [-Woverflow]
unique.cpp:29:1: error: static assertion failed: duplicates found
The first template parameter (in this case 0) to 'assert_equality' tells you the fist position of a duplicate string.
I am not sure that it is easily doable using the standard C++ preprocessor (I guess that it is not). You might use some other preprocessor (e.g. GPP)
You could make it the other way: generate some X-macro "header" file from some other source (using e.g. a tiny awk script, which would verify the unicity). Then customize your build (e.g. add some rules to your Makefile) to run that generating script to produce the header file.
Alternatively, if you insist that processing being done inside the compiler, and if your compiler is a recent GCC, consider customizing GCC with MELT (e.g. by adding appropriate builtins or pragmas doing the job).
In the previous century, I hacked a small Emacs function to do a similar job (uniquely numbering error messages) within the emacs editor (renumbering some #define-s before saving the C file).
I am going to assume that something like this will work:
addMessage(1, "Message1")
addMessage(2, "Message1")
Or:
addMessage(1, "Message") /* transforms into "Message_1" */
addMessage(2, "Message_1") /* transforms into "Message_1_2" */
Because the C preprocessor expands tokens lazily and prohibits defining a macro from within another macro, it is impossible to save the results of executing one macro so that another macro can make use of it.
On the other hand, it is definitely possible to force uniqueness of symbols:
#define addMessage(N, MSG) const char *_error_message_##N (void) { return MSG; }
Or:
#define addMessage(N, MSG) const char *_error_message_##N (void) { return MSG "_" #N; }
Because during the link step, duplicate symbols with the name _error_message_NUMBER will trigger an error. And because it is a function, it cannot be used inside of another function without triggering an error.
Assuming your compiler is still not C++11 compliant as you have not tagged appropiately. I am also assuming that you are not particular about the Error Message, its just that you want it to work. In which case, the following Macro Based Solution might work for you
#include <iostream>
#include <string>
#define ADD_MESSAGE(N, MSG) \
char * MSG; \
addMessage(N, #MSG);
void addMessage(int n, std::string msg)
{
std::cout << msg << std::endl;
}
int main() {
ADD_MESSAGE(1, Message1); //OK
ADD_MESSAGE(2, Message2); //OK
ADD_MESSAGE(3, MessageN); //OK
ADD_MESSAGE(4, Message2); //Compile error, Message2 has already been used
};
Compile Output
prog.cpp: In function ‘int main()’:
prog.cpp:17:17: error: redeclaration of ‘char* Message2’
ADD_MESSAGE(4, Message2); //Compile error, Message2 has already been used
^
prog.cpp:4:8: note: in definition of macro ‘ADD_MESSAGE’
char * MSG; \
^
prog.cpp:15:17: error: ‘char* Message2’ previously declared here
ADD_MESSAGE(2, Message2); //OK
^
prog.cpp:4:8: note: in definition of macro ‘ADD_MESSAGE’
char * MSG; \
^
If you don't care about large amounts of useless boiler plate then here's one that's entirely the preprocessor, so no worries about scope, and then checks that they are unique at program startup.
In a file:
#ifndef ERROR1
#define ERROR1 "1"
#endif
#ifndef ERROR2
#define ERROR2 "2"
#endif
...
#ifndef ERROR255
#define ERROR255 "255"
#endif
#include <assert.h>
#include <set>
#include <string>
class CheckUnique {
CheckUnique() {
std::set<std::string> s;
static const char *messages = {
#if HAVE_BOOST
# include <boost/preprocessor.hpp>
# define BOOST_PP_LOCAL_LIMITS (1, 254)
# define BOOST_PP_LOCAL_MACRO(N) ERROR ## N,
# include BOOST_PP_LOCAL_ITERATE()
#else // HAVE_BOOST
ERROR1,
ERROR2,
...
#endif // HAVE_BOOST
ERROR255
};
for (int i = 0; i < sizeof messages / sizeof *messages; i++) {
if (s.count(messages[i]))
assert(! "I found two error messages that were the same");
else
s.insert(messages[i]);
}
}
};
static CheckUnique check;
This file can then be #included at the end of each source file, or you can place it into a file of its own and include every single file that has a #define ERROR line in it. That way, as soon as the operating system loads the program, the constructor for check will run and throw the exception.
This also requires you to have access to the Boost.Preprocessor library (and it's header only so it's pretty easy to set up). Although if you can't use that, then you can just hard code the error macros as I have shown with the #if HAVE_BOOST block.
Most of the boiler plate here is pretty simple, so if you generated it with a program (like some sort of portable script) then it would make your life far easier, but it can still be done all in one shot.
I'm trying to create a proxy class for delayed load of a shared library.
One of the API function of the library is:
int AttachCWnd(CWnd* pControl);
So, I created a macro to easily declare and route calls from the proxy class to the library:
class CLibProxy {
public:
typedef int (*tAttachCWnd)(CWnd*);
tAttachCWnd m_fAttachCWnd;
};
#define DECL_ROUTE(name, ret, args) \
ret CLibProxy::name args \
{ \
if (m_hDLL) \
return m_f##name (args); \
return ret(); \
}
DECL_ROUTE(AttachCWnd, int, (CWnd* pControl));
But compilation fails on VS2010:
error C2275: 'CWnd' : illegal use of this type as an expression
Can anyone explain why?
Well, obvious mistake. Calling m_fAttachCWnd should not include the type declaration, but only the arguments:
return m_fAttachCWnd (CWnd* pControl);
should become
return m_fAttachCWnd (pControl);
Thanks #chris.
I'm building a tree-based debug/logging system for C++.
Its "user interface" is a macro which passes user-defined message and call site information (file, line, object address) to special function which then performs logging.
The function uses the object address to group messages by object instance.
Currently it looks like this:
// in logging system header
#define msg (event_level, message) \
do_logging_ (event_level, __FILE__, __LINE__, this, message)
...
// in code
msg (MSG_WARNING, "some text");
I want to ask, is there some uniform way (usable in the msg macro) to get NULL instead of this where this is not defined (global/static functions)?
You can change your macro definition:
#define msg (event_level, message, THIS) \
do_logging_ (event_level, __FILE__, __LINE__, THIS, message)
Usage:
msg (MSG_WARNING, "some text", this); // in member methods
msg (MSG_WARNING, "some text", NULL); // otherwise
I think this is not possible without modifying the code in your class you want to log. If you are willing to do that, however, you could derive all classes where you want logging functionality from a template like this one:
template <typename T>
class loggable_class
{
protected:
T* get_this() { return static_cast <T*> (this); }
};
For example:
class A : public loggable_class<A>
{
...
};
An additional global definition of the function get_this() will be used in non-member functions:
inline void* get_this()
{
return NULL;
}
The logging macro would look like:
#define msg (event_level, message) \
do_logging_ (event_level, __FILE__, __LINE__, get_this(), message)