Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

C++ Conversion Wizard

Visual D can help you converting your C++ code base to D. Even though it is capable of some quite extensive reorganization of the code, don't expect to get compilable and runnable code out of the box. Helping the converter with additional replacement rules and manual additional editing of the result might be necessary.

The conversion consists of a number of steps:

You can invoke the C++ conversion wizard from the Visual D menu.

Options:

When using the converter on the current selection (there is also a command VisualD.ConvertSelection that you can assign to a keyboard shortcut) you should select complete declarations, e.g. variable or class declarations and functions. Otherwise the parser will stumble.

This tool is the result of generalizing an attempt to convert the dmd front end code to D, so please don't be surprised to find some unexpected special casings from time to time. The result of that attempt was that the converted code was parsable, but did not pass all semantic stages.

Running from the console

There is also a command line version of this wizard available in the downloads folder: cpp2d.exe

You can pass a config file to the converter that has been saved by the wizard dialog.

cpp2d -config myoptions.c2d [files-specs...]
If you pass files to the program, file specifications in the configuration file are ignored.

See here for an example of a configuration file to get started on converting the dmd front end.

Examples

Here are some examples of what the converter can do for you:

Move member and field implementation into class declaration.
C++D

class C {
  // comments are usually kept
  static int x;
  DECL *foo(int flags = 0);
};
int C::x = 3;
// moved with the implementation
DECL *C::foo(int flags) { return NULL; }


struct C {
  // comments are usually kept
  static int x = 3;
  // moved with the implementation
 DECL *foo(int flags = 0) { return null; }
};

Convert constructor and call super constructor
C++D

struct A : B {
    A() : B(1) { }
    A(int x) : B(x) { }
};


class A : B {
    this() { super(1); }
    this(int x) { super(x); }
};

Split declarations for variables with different types
C++D

int a = sizeof(void *);
int x, *y = (int*)null;


int a = (void *).sizeof;
int x;
int *y = cast(int *)null;

Add enumerator type to constants of named enumerator values
C++D

typedef enum { e1, e2 } EX;
enum ENUM { kEnum };
int foo() {
    Ident id = (op == kEnum) ? 0 : 1;
}


 enum unnamed_1 { e1, e2 }alias unnamed_1 EX;
enum ENUM { kEnum };
int foo() {
    Ident id = (op == ENUM.kEnum) ? 0 : 1;
}

Simple template translations
C++D

template<typename TYPE>
struct ArrayBase : Array { 
    TYPE* data;
};
template<typename S, class T>
double foo(S s, T t) { return s+t; }


class ArrayBase( TYPE) : Array { 
    TYPE* data;
};

double foo( S, T)(S s, T t) { return s+t; }

Preprocessor macros are converted to enum, alias or templates
C++D

#define K1 1 // keep comment
#define K2 (K1+K1)
#define K3 K1
#define SQR(n) (n)*(n)


enum K1 =  1; // keep comment
enum K2 =  (K1+K1);
alias K3 K1;
 auto SQR( ARG1 )(ARG1 n) { return  n*n; }

Preprocessor conditionals are converted to static if or can be removed when specified in the "expansions" field
C++D

#define ABC 1
  a = 1;
#if ABC
  b = 2;
#endif
  c = 3;


enum ABC = 1;
  a = 1;
static if(ABC) {
  b = 2;
}
  c = 3;

It can deal with a number of complicated uses of preprocessor conditionals, but they can get much more difficult to read.
C++D

void foo(x) {
  if (x)
    c = 0;
#if COND1 // comment
  else if (a)
#elif COND2
  else if (b)
#endif
    c = 1;
}


void foo(x) {
  if (x)
    c = 0;
else if(true) static if(COND1) // comment
  /*else*/ if (a)
goto L_T4; else goto L_F4; else static if(COND2)
  /*else*/ if (b)
goto L_T4; else goto L_F4; else goto L_T4; else L_F4: if(0) L_T4:
    c = 1;
}