Dmitri Nesteruk
JetBrains
Managed language = C#, Java, D etc.
GC (garbage collector), Unicode, …
Unmanaged language
Something that compiles to native code
More control, less safety
C/C++, VHDL, etc.
Performance
Stop-the-world GC
Low-level control (e.g., SIMD)
Collections (containers), multithreading
Defense against reverse-engineering
C#, Java are easy to decompile
Hardware support
CUDA, Xeon Phi
Portability (surprise!)
Sudden desire to write everything in С++
Lex the source code
Build AST
Resolve symbols
Traverse the tree, translating it to a different
language
Perfect translation is (of course) impossible
Translate syntax with fidelity
Fill the gaps in what’s missing
Replace equivalent constructs
List<>  vector<>
Handle cases where 1-to-1
mapping is impossible
Integral types
Use types from <cstdint>
int int32_t, byte  uint8_t, etc.
float/double as-is
Extended precision types (System.Decimal)
Need external libs 
Slightly different init rules
Unicode 
Most LoB apps do not absolutely require Unicode (nice to
have)
Relatively safe option:
string  std::wstring
char  wchar_t
Slightly more careless option: string/char
A completely safe solution has to allow strings to be nullptr
I.e., you either use char* or option<string>
Expensive, tedious, just use myString.empty()
Unicode in source (identifiers, literals, …) won’t work
class Person
{
string name;
int age;
}
class Person {
std::string name;
int32_t age;
public:
Person();
};
Managed languages
Give types default values
Allow initialization right in the declaration
In both cases, initialization happens in the
(generated) ctor
In C++, types don’t have default values. So we
are forced to make a constructor ourselves
Property = field+getter+setter
Can be read or write-only
Can be automatic
Name of field not specified
explicitly
Offers no benefit over a field in C++
Can have an inline initializer
More ctor abuse 
Two options here
GetXxx/SetXxx (safe, tedious)
__declspec(property)
(not C++ standard, but nicer)
int age;
public int Age
{
get { return age; }
set { age = value; }
}
// automatic
public int Age
{ get; set; }
__declspec(property(get = GetAge, put = PutAge))
int Age;
int GetAge() const { return age; }
void PutAge(int value) { … }
// later
Person p;
p.Age = 123; // calls PutAge()
Used in many places, e.g.:
Handling UI interactions
Property change notifications
C++ doesn’t have them
Boost.Signals
Tricky since event subscription is done with +=
And unsubscription with −=
template <typename T> class
INotifyPropertyChanged
{
public:
signal<void(const T*, string)>
PropertyChanged;
};
class Player : public INotifyPropertyChanged<Player>
{
int age;
public:
__declspec(property(get = GetAge, put = PutAge)) int Age;
int GetAge() const { return age; }
void PutAge(int value)
{
if (value == age) return;
PropertyChanged(this, "Age"); // oops, a string! (macro?)
age = value;
}
“The big problem”
GC  non-GC translation
Store everything as shared_ptr
Replace every `new` with make_shared
Detecting use-cases for make_unique very
difficult
Circular references (weak_ptr<>?)
References require#includes
Need a list of typeheader for STL etc.
Circular references may need forward
declarations
Header groupings (at namespace or folder
level)
Very tricky internal consistency (topological sort)
Also a good idea for IDEs
Type translation is (relatively) easy
int  int32_t
List<T>  vector<T>
Function call translation is harder
List.Add()  vector.emplace_back(), but…
Value vs ref. stuff
We need two converters
One for .H files
Another for .CPP files (implementation)
The option of doing everything inline isn’t
considered
There are situations where 100% inlining doesn’t
work
Naming convention
Clean Unicode handling
Automated API mapping
Questions?
dn@jetbrains.com
@dnesteruk
Come to the JB booth! (R#C++, CLion)

Converting Managed Languages to C++

  • 1.
  • 2.
    Managed language =C#, Java, D etc. GC (garbage collector), Unicode, … Unmanaged language Something that compiles to native code More control, less safety C/C++, VHDL, etc.
  • 3.
    Performance Stop-the-world GC Low-level control(e.g., SIMD) Collections (containers), multithreading Defense against reverse-engineering C#, Java are easy to decompile Hardware support CUDA, Xeon Phi Portability (surprise!) Sudden desire to write everything in С++
  • 4.
    Lex the sourcecode Build AST Resolve symbols Traverse the tree, translating it to a different language Perfect translation is (of course) impossible
  • 5.
    Translate syntax withfidelity Fill the gaps in what’s missing Replace equivalent constructs List<>  vector<> Handle cases where 1-to-1 mapping is impossible
  • 6.
    Integral types Use typesfrom <cstdint> int int32_t, byte  uint8_t, etc. float/double as-is Extended precision types (System.Decimal) Need external libs  Slightly different init rules
  • 7.
    Unicode  Most LoBapps do not absolutely require Unicode (nice to have) Relatively safe option: string  std::wstring char  wchar_t Slightly more careless option: string/char A completely safe solution has to allow strings to be nullptr I.e., you either use char* or option<string> Expensive, tedious, just use myString.empty() Unicode in source (identifiers, literals, …) won’t work
  • 8.
    class Person { string name; intage; } class Person { std::string name; int32_t age; public: Person(); };
  • 9.
    Managed languages Give typesdefault values Allow initialization right in the declaration In both cases, initialization happens in the (generated) ctor In C++, types don’t have default values. So we are forced to make a constructor ourselves
  • 10.
    Property = field+getter+setter Canbe read or write-only Can be automatic Name of field not specified explicitly Offers no benefit over a field in C++ Can have an inline initializer More ctor abuse  Two options here GetXxx/SetXxx (safe, tedious) __declspec(property) (not C++ standard, but nicer) int age; public int Age { get { return age; } set { age = value; } } // automatic public int Age { get; set; }
  • 11.
    __declspec(property(get = GetAge,put = PutAge)) int Age; int GetAge() const { return age; } void PutAge(int value) { … } // later Person p; p.Age = 123; // calls PutAge()
  • 12.
    Used in manyplaces, e.g.: Handling UI interactions Property change notifications C++ doesn’t have them Boost.Signals Tricky since event subscription is done with += And unsubscription with −=
  • 13.
    template <typename T>class INotifyPropertyChanged { public: signal<void(const T*, string)> PropertyChanged; };
  • 14.
    class Player :public INotifyPropertyChanged<Player> { int age; public: __declspec(property(get = GetAge, put = PutAge)) int Age; int GetAge() const { return age; } void PutAge(int value) { if (value == age) return; PropertyChanged(this, "Age"); // oops, a string! (macro?) age = value; }
  • 15.
    “The big problem” GC non-GC translation Store everything as shared_ptr Replace every `new` with make_shared Detecting use-cases for make_unique very difficult Circular references (weak_ptr<>?)
  • 16.
    References require#includes Need alist of typeheader for STL etc. Circular references may need forward declarations Header groupings (at namespace or folder level) Very tricky internal consistency (topological sort) Also a good idea for IDEs
  • 17.
    Type translation is(relatively) easy int  int32_t List<T>  vector<T> Function call translation is harder List.Add()  vector.emplace_back(), but… Value vs ref. stuff
  • 18.
    We need twoconverters One for .H files Another for .CPP files (implementation) The option of doing everything inline isn’t considered There are situations where 100% inlining doesn’t work
  • 20.
    Naming convention Clean Unicodehandling Automated API mapping
  • 21.