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.
Related
I am writing a C++ program and I have predefined objects Serial1, Serial2, Serial3, etc. I need to make a function to operate on only one of them depending on a numeric input known at compile time. I use the concatenation macro #define SER(x) Serial##x but in my main if use SER(port).read() and port is an int equal to 1, expression expands to Serialport.read() instead of Serial1.read(). However, SER(1).read() gives the required result. How can I force the preprocessor to evaluate variable port and use its value in the expansion?
BTW, I don't know the class name of Serial1, Serial2, etc so I cannot design a workaround using pointers or references
EDIT: After seeing some answers, I need to add some clarification. I need to be able to use this function with all Serial1, Serial2, etc. by calling it multiple times in a SINGLE RUN of my code. Sorry for not making that clear before!
You need to use two levels of macros to accomplish what you are trying.
#define SER2(x) Serial##x
#define SER(x) SER2(x)
Here's a test program that demonstrates the concept.
#include <iostream>
#include <string>
struct Port
{
Port(std::string name) : name_(name) {}
void write()
{
std::cout << name_ << std::endl;
}
std::string name_;
};
Port Serial1("PORT1");
Port Serial2("PORT2");
#define SER2(x) Serial##x
#define SER(x) SER2(x)
int main()
{
SER(port).write();
}
Command to build:
g++ -std=c++11 -Wall socc.cc -o socc -Dport=1
Output:
PORT1
Command to build:
g++ -std=c++11 -Wall socc.cc -o socc -Dport=2
Output:
PORT2
Update
With the updated question, the only sensible approach is to use an array of objects and use the appropriate element of the array based on the run time data.
The fact that you don't know the type doesn't really matter: decltype(Serial1) will give that. Do you know whether they all have the same type? Because if they don't, no single C++ function can return them directly. And if they don't even have a common base class, it's even harder.
The template mechanism is more powerful than the preprocessor, so it makes sense to draft that:
template<int N> struct Serial { };
template<> struct Serial<1> { static decltype(Serial1)* const ptr = &Serial1 };
template<> struct Serial<2> { static decltype(Serial2)* const ptr = &Serial3 };
template<> struct Serial<3> { static decltype(Serial3)* const ptr = &Serial3 };
// You can now use Serial<8/2-2>.ptr->
Of course, writing out the template specializations is boring. So let's get Boost.PP :
#define BOOST_PP_LOCAL_MACRO (1, 7) // Assuming you have ports 1 to 7
#define BOOST_PP_LOCAL_MACRO(n) \
template<> struct Serial<n> { \
static decltype(BOOST_PP_CAT(Serial,n))* const ptr = &Serial##n; \
};
#include BOOST_PP_LOCAL_ITERATE()
Yes, that last line is a #include without quotes. And no, I'm not sure if this is an improvement ;)
The context of my situation is pretty hard to explain exhaustively here but : I am using an external toolset (lib, bins, etc.) which generates some c++ code from a proprietary IDL file. For a given type T, it generates a T_Result class. The generated code is then integrated to my project.
Now, I am trying to generate a type based on the type of a template parameter.
#define GENTYPE(x) x ## _Result
// class coming from generated includes. Copied here for clarity.
class int_Result
{};
template < class T >
class Connector
{
GENTYPE(T) _result;
public:
};
int main()
{
Connector<int> t;
/* ... */
}
Of course, this does not work because the c-preprocessor uses the T value as it, so the GENTYPE macro is expanded inside the Connector class as T_Result instead of the wanted int_Result class.
One could use #define to produce the whole class but then very difficult to maintain, debug, etc.
Does anyone knows a trick to achieve this goal ?
Instead of a macro generating Connector, we use a macro to generate a traits class that maps T to T_result. Then Connector just uses that traits class.
template<class T>struct result_type;
#define MRT(T) \
template<>struct result_type<T>{ \
using type = GENTYPE(T); \
}
template<class T>using result_t=typename result_type<T>::type;
now simply do a MRT(int); to make result_t<int> be to int_result. The macro must be used before the first use of result_t<int>. Failure to do MRT(int) makes result_t<int> an error.
This assumes C++11 support: it is 2015.
In Connector just do result_t<T> _result;
Use of MRT is optional, as a strait
template<>struct result_type<int>{ using type=GENTYPE(int); };
or even
template<>struct result_type<int>{ using type=int_result; };
isn't all that verbose, and reduces the number of layers of macros. It does violate DRY (don't repeat yourself) however.
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.
The following works just-fine in MSVC2008 and MSVC2010:
class Foo {
public:
static void FuncA(void) {
FuncB(); // "FuncB()" NOT DECLARED YET? WORKS, MSVC2008
}
static void FuncB(void);
};
Yes, this is kinda weird: FuncA() calls FuncB(), even though (at that point) FuncB() is not-yet-declared. However, MSVC2008 and MSVC2010 thinks this is fine.
Apparently, gcc doesn't think this is fine -- FuncB was not declared in this scope.
ISSUE: I have a bunch of these, and it would be a "pain" to declare them, and later define them. Further, it would be hard to "order" them properly so each only calls functions after those were declared. But, I'm guessing I need to declare-first-then-define-later?
Are the rules different for whether these functions are template-or-not, or defined within a template-class or not?
Specifically, I've noticed Microsoft is very "late-compiling" where it accepts tons of inter-coupled code, and LATER resolves (at compile, when the template-parameterization is triggered), while gcc seems to want to compile now when it "sees" the code (an initial pass for correctness, and again during parameterization/invocation).
(This problem shows up as we port our Microsoft code to Linux/gcc.)
===UPDATE===
The following are "alternate" scenarios that we have (in this code-porting effort), and would your answer change based on any of these?
// Alternate-Scenario-B
class Foo2 {
public:
template<typename SOME_TYPE>
static void FuncA(const SOME_TYPE& some_type) {
FuncB(some_type); // "FuncB()" NOT DECLARED YET? WORKS, MSVC2008
}
template<typename SOME_TYPE>
static void FuncB(const SOME_TYPE& some_type);
};
...and:
// Alternate-Scenario-C
template<typename SOME_TYPE>
class Foo3 {
public:
static void FuncA(const SOME_TYPE& some_type) {
FuncB(some_type); // "FuncB()" NOT DECLARED YET? WORKS, MSVC2008
}
static void FuncB(const SOME_TYPE& some_type);
};
===UPDATE+2===
Thanks for the comments, where consensus seems that this is valid C++ code, and should work (as #Adam suggested, a function "defined-inline" should behave as if it were defined after the class, and should be able to call functions defined in the class interface after that inline definition).
MORE INFORMATION:
Yes, I really have this compile error from the first example in the FuncA() inline implementation:
'FuncB' is not a member of 'Foo'
...using:
gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
(Recall that this works on MSVC2008/MSVC2010).
I realize now that my code-example (above) is insufficient (the above example does not show this error on gcc), here are some more details:
Foo has a base-class (I don't think that should matter)
Foo defines an internal enum which is passed through these funcs (I don't think this matters)
these functions are "expanded" through a macro (I think significant -- see below)
there are fifty-six (56) of these functions (I think significant -- see below)
A more complete code example would be (and I am not proud of this):
#define FOO_FUNCS(CLASS_NAME,CLASS_ENUM) \
static void FuncA(CLASS_ENUM value_enum) { \
FuncB(value_enum); /*PROBLEM*/ \
} \
static void FuncB(CLASS_ENUM value_enum) { \
FuncC(value_enum); \
} \
/*...THERE ARE 56 FUNCS IN THIS MACRO, THREE LINES EACH...*/
class Foo : public FooParent {
public:
enum FooEnum { FOO_ONE, FOO_TWO };
FOO_FUNCS(Foo,FooEnum) // EXPAND THE 56 FUNCS
};
CODE INTENT: The FooParent base class has implementation that is intended to be "shared" by (many) derived classes. The derived classes define their own enum values. Functions that used these enum values were implemented through a macro (because the FooParent is not a template<>, and cannot rely upon the derived-enum).
Curious behavior:
If the FooA(){FooB();} nesting references a function defined "later" by only a "few-lines", then gcc compiles fine. However, if the yet-to-be-declared function is much later, like Foo2(){Foo53();}, then gcc concludes that Foo53() is not a member of the class (but it is).
Here's what I think is going on:
There seems to be an issue with lots-of-code (for 56 functions) that are physically on "one-line". If I take these functions out of the macro, AND if I remove \ escape-line-endings, then gcc compiles fine.
Thus, I think the (code-porting) answer is:
don't use a preprocessor-macro
make a FooParentBase<> template class derived from FooParent, from which we derive Foo, which requires the typename Foo::enum as a template-parameter
I'm fine with these changes (I didn't like the macro), but I find it weird that gcc seems to have an issue here.
Are there other suggestions for how to fix this? (Is the above re-factoring what you would do?)
All three of your scenarios are correct and compile with both g++ and clang.
Your code looks perfectly legal to me. Inline definitions within a class definition are supposed to be treated equivalent to declarations with an inline definition immediately following the class definition (by which time the declaration of FuncB() would be available).
My version of GCC accepts this code as valid (all three examples you post, assuming I provide trivial implementations of each FuncB(), of course).
~$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
...
I believe more information is needed here. Perhaps post your version of GCC and the specific error message you're seeing.
========REPLY TO LATER UPDATE=======
I've tried your latest example with 70 functions in the macro, and it's still working for me in gcc 4.6.3. Here is the test I tried (with the macro shortened in the obvious way):
#include <iostream>
using std::cout;
struct FooParent {
static void Func71( int ) {
cout << "Called\n";
}
};
#define FOO_FUNCS(CLASS_NAME,CLASS_ENUM) \
static void Func1(CLASS_ENUM value_enum) { \
Func2(value_enum); /PROBLEM/ \
} \
static void Func2(CLASS_ENUM value_enum) { \
Func3(value_enum); \
} \
/* Functions Func3...Func69 snipped */ \
static void Func70(CLASS_ENUM value_enum) { \
Func71(value_enum); \
} \
/...THERE ARE 70 FUNCS IN THIS MACRO, THREE LINES EACH.../
class Foo : public FooParent {
public:
enum FooEnum { FOO_ONE, FOO_TWO };
FOO_FUNCS(Foo,FooEnum) // EXPAND THE 70 FUNCS
};
int main() {
Foo::Func1(Foo::FOO_ONE);
}
I have
namespace src {
struct src_bar;
void src_baz();
template<class T> class src_qux;
}
which I'd like to reference as
namespace dst {
struct dst_bar;
void dst_baz();
template<class T> class dst_qux;
}
meaning that I'd like to "rename" or "alias" or "relabel" names from src.
For dst_bar one can of course use namespace dst { typedef src_bar dst_bar; }. Is there some (non-macro) equivalent allowing me to rename src::src_baz as dst::dst_baz and src::src_qux as dst::dst_qux?
Unless I'm mistaken, neither a using statement nor a namespace alias can accomplish the other two. Writing templated forwarding functions for dst_baz() is a possibility but requires knowledge of the arity of src_baz. Template typedefs could have dst_qux<T>::type be src_qux<T> but the indirection adds verbosity.
FWIW, my use case is taking C names like somepackage_someportion_somefuncA and providing a namespaced-friendly version somepackage::someportion::somefuncA so that other folks can employ using somepackage::someportion for brevity.
For functions you will have to manually forward the requests. For non-template types you can just typedef. For template types, y can use the new using feature of c++11 To create a typedef-style alias for a template, if your compiler supports it, or else you are basically out of luck.
No, you cannot "rename" something so that it no longer uses its original name.
However, you can get the same effect via trickery.
First, import the header for the defines you want to corral inside a namespace block:
namespace foo {
#include "src_stuff.h"
}
Now you have foo::src::src_bar and friends.
Then, use typedef liberally:
namespace bar {
typedef foo::src::src_bar dst_bar;
}
Voila, you've got a bar::dst_bar which is the same as src::src_bar would have been. If you don't care about the definitions remaining available under the old names in addition, skip the first step and just make typedefs for convenience. That's what they're for, after all.
If usage of macros is an acceptable option for you then here is one solution:
// declare this macro in some common file
#define CREATE(SCOPE) \
namespace SCOPE { \
struct SCOPE## _bar; \
void SCOPE## _baz(); \
template<class T> class SCOPE## _qux; \
}
Usage:
CREATE(src);
CREATE(dst);