Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,25 @@ public class CSharpToCppTransformer : TextTransformer
// AppDomain.CurrentDomain.ProcessExit -= OnProcessExit;
// /* No translation. It is not possible to unsubscribe from std::atexit. */
(new Regex(@"AppDomain\.CurrentDomain\.ProcessExit -= ([a-zA-Z_][a-zA-Z0-9_]*);"), "/* No translation. It is not possible to unsubscribe from std::atexit. */", 0),
// C++ Modern Style Improvements
// std::string &val
// std::string& val
(new Regex(@"(?<type>std::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) &(?<var>[a-zA-Z_][a-zA-Z0-9_]*)"), "${type}& ${var}", 0),
// Type *val
// Type* val
(new Regex(@"(?<type>std::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) \*(?<var>[a-zA-Z_][a-zA-Z0-9_]*)"), "${type}* ${var}", 0),
// constructor(std::string string) : field(string)
// constructor(std::string string) : field(std::move(string))
(new Regex(@"(?<constructor>[a-zA-Z_][a-zA-Z0-9_]*)\((?<params>[^)]*std::string [a-zA-Z_][a-zA-Z0-9_]*[^)]*)\)(?<init>\s*:\s*[^{]*?)(?<fieldAssignment>(?<field>[a-zA-Z_][a-zA-Z0-9_]*)\((?<param>[a-zA-Z_][a-zA-Z0-9_]*)\))"), "${constructor}(${params})${init}${field}(std::move(${param}))", 0),
// function(std::string param)
// function(const std::string& param)
(new Regex(@"(?<func>[a-zA-Z_][a-zA-Z0-9_]*)\((?<before>[^)]*?)(?<sep>(^|\(|, ))std::string (?<param>[a-zA-Z_][a-zA-Z0-9_]*)(?<after>[^)]*)\)"), "${func}(${before}${sep}const std::string& ${param}${after})", 0),
// function(std::vector<Type> param)
// function(const std::vector<Type>& param)
(new Regex(@"(?<func>[a-zA-Z_][a-zA-Z0-9_]*)\((?<before>[^)]*?)(?<sep>(^|\(|, ))std::(vector|string|unordered_set|unordered_map|set|map)<[^>]+> (?<param>[a-zA-Z_][a-zA-Z0-9_]*)(?<after>[^)]*)\)"), "${func}(${before}${sep}const std::${2}<${3}>& ${param}${after})", 0),
// vector.push_back(value)
// vector.push_back(std::move(value)) for non-const value parameters
(new Regex(@"(?<container>[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?<value>[a-zA-Z_][a-zA-Z0-9_]*)\)(?!\s*//.*const)"), "${container}.push_back(std::move(${value}))", 0),
}.Cast<ISubstitutionRule>().ToList();

/// <summary>
Expand Down Expand Up @@ -752,6 +771,14 @@ public class CSharpToCppTransformer : TextTransformer
// \n\n}
// \n}
(new Regex(@"\r?\n[ \t]*\r?\n(?<end>[ \t]*})"), Environment.NewLine + "${end}", 10),
// C++ Universal Reference and std::forward for templates
// template<typename T> void func(T arg)
// template<typename T> void func(T&& arg)
(new Regex(@"(?<before>template\s*<\s*typename\s+(?<typeParam>[a-zA-Z_][a-zA-Z0-9_]*)\s*>\s*[^(]*\([^)]*?)(?<type>\k<typeParam>) (?<param>[a-zA-Z_][a-zA-Z0-9_]*)(?<after>[^)]*\))"), "${before}${type}&& ${param}${after}", 0),
// Inside template functions, use std::forward for perfect forwarding
// container.push_back(templateParam)
// container.push_back(std::forward<decltype(templateParam)>(templateParam))
(new Regex(@"(?<container>[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?<param>[a-zA-Z_][a-zA-Z0-9_]*)\)(?=.*template.*\k<param>)"), "${container}.push_back(std::forward<decltype(${param})>(${param}))", 0),
}.Cast<ISubstitutionRule>().ToList();

/// <summary>
Expand Down
27 changes: 27 additions & 0 deletions python/cs2cpp/cs2cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,25 @@ def __init__(
# AppDomain.CurrentDomain.ProcessExit -= OnProcessExit;
# /* No translation. It is not possible to unsubscribe from std::atexit. */
SubRule(r"AppDomain\.CurrentDomain\.ProcessExit -= ([a-zA-Z_][a-zA-Z0-9_]*);", r"/* No translation. It is not possible to unsubscribe from std::atexit. */", max_repeat=0),
# C++ Modern Style Improvements
# std::string &val
# std::string& val
SubRule(r"(?P<type>std::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) &(?P<var>[a-zA-Z_][a-zA-Z0-9_]*)", r"\g<type>& \g<var>", max_repeat=0),
# Type *val
# Type* val
SubRule(r"(?P<type>std::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) \*(?P<var>[a-zA-Z_][a-zA-Z0-9_]*)", r"\g<type>* \g<var>", max_repeat=0),
# constructor(std::string string) : field(string)
# constructor(std::string string) : field(std::move(string))
SubRule(r"(?P<constructor>[a-zA-Z_][a-zA-Z0-9_]*)\((?P<params>[^)]*std::string [a-zA-Z_][a-zA-Z0-9_]*[^)]*)\)(?P<init>\s*:\s*[^{]*?)(?P<fieldAssignment>(?P<field>[a-zA-Z_][a-zA-Z0-9_]*)\((?P<param>[a-zA-Z_][a-zA-Z0-9_]*)\))", r"\g<constructor>(\g<params>)\g<init>\g<field>(std::move(\g<param>))", max_repeat=0),
# function(std::string param)
# function(const std::string& param)
SubRule(r"(?P<func>[a-zA-Z_][a-zA-Z0-9_]*)\((?P<before>[^)]*?)(?P<sep>(^|\(|, ))std::string (?P<param>[a-zA-Z_][a-zA-Z0-9_]*)(?P<after>[^)]*)\)", r"\g<func>(\g<before>\g<sep>const std::string& \g<param>\g<after>)", max_repeat=0),
# function(std::vector<Type> param)
# function(const std::vector<Type>& param)
SubRule(r"(?P<func>[a-zA-Z_][a-zA-Z0-9_]*)\((?P<before>[^)]*?)(?P<sep>(^|\(|, ))std::(?P<container>vector|string|unordered_set|unordered_map|set|map)<(?P<type>[^>]+)> (?P<param>[a-zA-Z_][a-zA-Z0-9_]*)(?P<after>[^)]*)\)", r"\g<func>(\g<before>\g<sep>const std::\g<container><\g<type>>& \g<param>\g<after>)", max_repeat=0),
# vector.push_back(value)
# vector.push_back(std::move(value)) for non-const value parameters
SubRule(r"(?P<container>[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?P<value>[a-zA-Z_][a-zA-Z0-9_]*)\)(?!\s*//.*const)", r"\g<container>.push_back(std::move(\g<value>))", max_repeat=0),
]


Expand Down Expand Up @@ -745,4 +764,12 @@ def __init__(
# \n\n}
# \n}
SubRule(r"\r?\n[ \t]*\r?\n(?P<end>[ \t]*})", "\n\g<end>", max_repeat=10),
# C++ Universal Reference and std::forward for templates
# template<typename T> void func(T arg)
# template<typename T> void func(T&& arg)
SubRule(r"(?P<before>template\s*<\s*typename\s+(?P<typeParam>[a-zA-Z_][a-zA-Z0-9_]*)\s*>\s*[^(]*\([^)]*?)(?P<type>\k<typeParam>) (?P<param>[a-zA-Z_][a-zA-Z0-9_]*)(?P<after>[^)]*\))", r"\g<before>\g<type>&& \g<param>\g<after>", max_repeat=0),
# Inside template functions, use std::forward for perfect forwarding
# container.push_back(templateParam)
# container.push_back(std::forward<decltype(templateParam)>(templateParam))
SubRule(r"(?P<container>[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?P<param>[a-zA-Z_][a-zA-Z0-9_]*)\)(?=.*template.*\k<param>)", r"\g<container>.push_back(std::forward<decltype(\g<param>)>(\g<param>))", max_repeat=0),
]
72 changes: 72 additions & 0 deletions verification_examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# C++ Style Improvements Verification

This document shows the transformations our regex patterns should perform:

## 1. Type Reference Style (Type& val instead of Type &val)

**Pattern:** `(?<type>std::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) &(?<var>[a-zA-Z_][a-zA-Z0-9_]*)`
**Replacement:** `${type}& ${var}`

Examples:
- `std::string &value` β†’ `std::string& value`
- `MyType &ref` β†’ `MyType& ref`

## 2. Type Pointer Style (Type* val instead of Type *val)

**Pattern:** `(?<type>std::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) \*(?<var>[a-zA-Z_][a-zA-Z0-9_]*)`
**Replacement:** `${type}* ${var}`

Examples:
- `int *pointer` β†’ `int* pointer`
- `std::string *ptr` β†’ `std::string* ptr`

## 3. Constructor std::move Pattern

**Pattern:** `(?<constructor>[a-zA-Z_][a-zA-Z0-9_]*)\((?<params>[^)]*std::string [a-zA-Z_][a-zA-Z0-9_]*[^)]*)\)(?<init>\s*:\s*[^{]*?)(?<fieldAssignment>(?<field>[a-zA-Z_][a-zA-Z0-9_]*)\((?<param>[a-zA-Z_][a-zA-Z0-9_]*)\))`
**Replacement:** `${constructor}(${params})${init}${field}(std::move(${param}))`

Examples:
- `MyClass(std::string str) : field(str)` β†’ `MyClass(std::string str) : field(std::move(str))`

## 4. Const Reference for std::string Parameters

**Pattern:** `(?<func>[a-zA-Z_][a-zA-Z0-9_]*)\((?<before>[^)]*?)(?<sep>(^|\(|, ))std::string (?<param>[a-zA-Z_][a-zA-Z0-9_]*)(?<after>[^)]*)\)`
**Replacement:** `${func}(${before}${sep}const std::string& ${param}${after})`

Examples:
- `function(std::string param)` β†’ `function(const std::string& param)`
- `method(int x, std::string str)` β†’ `method(int x, const std::string& str)`

## 5. Const Reference for Container Parameters

**Pattern:** `(?<func>[a-zA-Z_][a-zA-Z0-9_]*)\((?<before>[^)]*?)(?<sep>(^|\(|, ))std::(vector|string|unordered_set|unordered_map|set|map)<[^>]+> (?<param>[a-zA-Z_][a-zA-Z0-9_]*)(?<after>[^)]*)\)`
**Replacement:** `${func}(${before}${sep}const std::${2}<${3}>& ${param}${after})`

Examples:
- `function(std::vector<int> vec)` β†’ `function(const std::vector<int>& vec)`

## 6. std::move for push_back

**Pattern:** `(?<container>[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?<value>[a-zA-Z_][a-zA-Z0-9_]*)\)(?!\s*//.*const)`
**Replacement:** `${container}.push_back(std::move(${value}))`

Examples:
- `vector.push_back(value)` β†’ `vector.push_back(std::move(value))`

## 7. Universal Reference for Templates

**Pattern:** `(?<before>template\s*<\s*typename\s+(?<typeParam>[a-zA-Z_][a-zA-Z0-9_]*)\s*>\s*[^(]*\([^)]*?)(?<type>\k<typeParam>) (?<param>[a-zA-Z_][a-zA-Z0-9_]*)(?<after>[^)]*\))`
**Replacement:** `${before}${type}&& ${param}${after}`

Examples:
- `template<typename T> void func(T arg)` β†’ `template<typename T> void func(T&& arg)`

## 8. std::forward for Perfect Forwarding

**Pattern:** `(?<container>[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?<param>[a-zA-Z_][a-zA-Z0-9_]*)\)(?=.*template.*\k<param>)`
**Replacement:** `${container}.push_back(std::forward<decltype(${param})>(${param}))`

Examples:
- In template context: `container.push_back(param)` β†’ `container.push_back(std::forward<decltype(param)>(param))`

All these patterns follow modern C++ best practices as requested in the issue.
Loading