StoneThrow
StoneThrow

Reputation: 6285

Can I use the preprocessor to replace one type declaration with another?

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

Answers (2)

MSalters
MSalters

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

Davislor
Davislor

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

Related Questions