Reputation: 6285
The following code shows class A
, B
, and C
. An A
is the ctor argument to B
and C
.
Macro X
conditionally creates either an A
or a B
instance.
#include <iostream>
class A
{
};
class B
{
public:
B( const A& a ) : a_( a ) { std::cout << __FUNCTION__ << std::endl; }
private:
const A& a_;
};
class C
{
public:
C( const A& a, const std::string& file, int line )
: b_( ( (std::cout << "@ " << file << ":" << line << std::endl), a ) )
{
std::cout << "After" << std::endl;
}
private:
B b_;
};
#undef DEBUG
#ifdef DEBUG
#define X( Z ) B b##Z( Z )
#else
#define X( Z ) C c##Z( Z, __FILE__, __LINE__ )
#endif
int main( int argc, char* argv[] )
{
A a;
B b( a );
C c( a, __FILE__, __LINE__ );
X( a );
return 0;
}
I was asked to rename B
to SomethingElse
and create a B
macro such that all existing instances of B b( a )
becomes either a SomethingElse
or a C
.
I don't think this ask can be satisfied because SomethingElse
and C
constructors have different signatures, so I cannot just do:
#ifdef DEBUG
#define B SomethingElse
#else
#define B C
#endif
Are there C preprocessor experts out there who can confirm whether or not there is a way to satisfy the ask? Can a macro be created such that all existing instantiations of B
can be swapped at compile-time to instantiations of SomethingElse
or C
? You can assume the second and third arguments to C
will be __FILE__
and __LINE__
.
Upvotes: 0
Views: 216
Reputation: 179991
This is fairly easy, once you realize that C++ inheritance implements an IS-A relation.
You define a new class realB<const str* FILE, int LINE>
, which IS-A (derives from) either C
or SomethingElse
. The only small trick you need is a helper constexpr const char*
to capture __FILE__
, see here.
Now realB<FILE, LINE>
has a ctor which takes only one parameter, A a
, but if it inherits from C
it can still pass (a, FILE, LINE)
to C::C
Upvotes: 4
Reputation: 15144
I'm on my phone, so this is untested, but you might try:
#if DEBUG
# define CREATEB(a) somethingelse(a)
#else
# define CREATEB(a) C( (a), __FILE__, __LINE__ )
#endif
These should work on the right-hand-side of an auto
or reference-to-base-class declaration.
Upvotes: 0