diff --git a/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs b/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs index 2f5dceb..7dd6930 100644 --- a/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs +++ b/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs @@ -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(@"(?std::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) &(?[a-zA-Z_][a-zA-Z0-9_]*)"), "${type}& ${var}", 0), + // Type *val + // Type* val + (new Regex(@"(?std::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) \*(?[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(@"(?[a-zA-Z_][a-zA-Z0-9_]*)\((?[^)]*std::string [a-zA-Z_][a-zA-Z0-9_]*[^)]*)\)(?\s*:\s*[^{]*?)(?(?[a-zA-Z_][a-zA-Z0-9_]*)\((?[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(@"(?[a-zA-Z_][a-zA-Z0-9_]*)\((?[^)]*?)(?(^|\(|, ))std::string (?[a-zA-Z_][a-zA-Z0-9_]*)(?[^)]*)\)"), "${func}(${before}${sep}const std::string& ${param}${after})", 0), + // function(std::vector param) + // function(const std::vector& param) + (new Regex(@"(?[a-zA-Z_][a-zA-Z0-9_]*)\((?[^)]*?)(?(^|\(|, ))std::(vector|string|unordered_set|unordered_map|set|map)<[^>]+> (?[a-zA-Z_][a-zA-Z0-9_]*)(?[^)]*)\)"), "${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(@"(?[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?[a-zA-Z_][a-zA-Z0-9_]*)\)(?!\s*//.*const)"), "${container}.push_back(std::move(${value}))", 0), }.Cast().ToList(); /// @@ -752,6 +771,14 @@ public class CSharpToCppTransformer : TextTransformer // \n\n} // \n} (new Regex(@"\r?\n[ \t]*\r?\n(?[ \t]*})"), Environment.NewLine + "${end}", 10), + // C++ Universal Reference and std::forward for templates + // template void func(T arg) + // template void func(T&& arg) + (new Regex(@"(?template\s*<\s*typename\s+(?[a-zA-Z_][a-zA-Z0-9_]*)\s*>\s*[^(]*\([^)]*?)(?\k) (?[a-zA-Z_][a-zA-Z0-9_]*)(?[^)]*\))"), "${before}${type}&& ${param}${after}", 0), + // Inside template functions, use std::forward for perfect forwarding + // container.push_back(templateParam) + // container.push_back(std::forward(templateParam)) + (new Regex(@"(?[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?[a-zA-Z_][a-zA-Z0-9_]*)\)(?=.*template.*\k)"), "${container}.push_back(std::forward(${param}))", 0), }.Cast().ToList(); /// diff --git a/python/cs2cpp/cs2cpp.py b/python/cs2cpp/cs2cpp.py index 44ab7bb..0fabfaf 100644 --- a/python/cs2cpp/cs2cpp.py +++ b/python/cs2cpp/cs2cpp.py @@ -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"(?Pstd::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) &(?P[a-zA-Z_][a-zA-Z0-9_]*)", r"\g& \g", max_repeat=0), + # Type *val + # Type* val + SubRule(r"(?Pstd::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) \*(?P[a-zA-Z_][a-zA-Z0-9_]*)", r"\g* \g", max_repeat=0), + # constructor(std::string string) : field(string) + # constructor(std::string string) : field(std::move(string)) + SubRule(r"(?P[a-zA-Z_][a-zA-Z0-9_]*)\((?P[^)]*std::string [a-zA-Z_][a-zA-Z0-9_]*[^)]*)\)(?P\s*:\s*[^{]*?)(?P(?P[a-zA-Z_][a-zA-Z0-9_]*)\((?P[a-zA-Z_][a-zA-Z0-9_]*)\))", r"\g(\g)\g\g(std::move(\g))", max_repeat=0), + # function(std::string param) + # function(const std::string& param) + SubRule(r"(?P[a-zA-Z_][a-zA-Z0-9_]*)\((?P[^)]*?)(?P(^|\(|, ))std::string (?P[a-zA-Z_][a-zA-Z0-9_]*)(?P[^)]*)\)", r"\g(\g\gconst std::string& \g\g)", max_repeat=0), + # function(std::vector param) + # function(const std::vector& param) + SubRule(r"(?P[a-zA-Z_][a-zA-Z0-9_]*)\((?P[^)]*?)(?P(^|\(|, ))std::(?Pvector|string|unordered_set|unordered_map|set|map)<(?P[^>]+)> (?P[a-zA-Z_][a-zA-Z0-9_]*)(?P[^)]*)\)", r"\g(\g\gconst std::\g<\g>& \g\g)", max_repeat=0), + # vector.push_back(value) + # vector.push_back(std::move(value)) for non-const value parameters + SubRule(r"(?P[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?P[a-zA-Z_][a-zA-Z0-9_]*)\)(?!\s*//.*const)", r"\g.push_back(std::move(\g))", max_repeat=0), ] @@ -745,4 +764,12 @@ def __init__( # \n\n} # \n} SubRule(r"\r?\n[ \t]*\r?\n(?P[ \t]*})", "\n\g", max_repeat=10), + # C++ Universal Reference and std::forward for templates + # template void func(T arg) + # template void func(T&& arg) + SubRule(r"(?Ptemplate\s*<\s*typename\s+(?P[a-zA-Z_][a-zA-Z0-9_]*)\s*>\s*[^(]*\([^)]*?)(?P\k) (?P[a-zA-Z_][a-zA-Z0-9_]*)(?P[^)]*\))", r"\g\g&& \g\g", max_repeat=0), + # Inside template functions, use std::forward for perfect forwarding + # container.push_back(templateParam) + # container.push_back(std::forward(templateParam)) + SubRule(r"(?P[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?P[a-zA-Z_][a-zA-Z0-9_]*)\)(?=.*template.*\k)", r"\g.push_back(std::forward)>(\g))", max_repeat=0), ] diff --git a/verification_examples.md b/verification_examples.md new file mode 100644 index 0000000..30d7ad3 --- /dev/null +++ b/verification_examples.md @@ -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:** `(?std::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) &(?[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:** `(?std::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) \*(?[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:** `(?[a-zA-Z_][a-zA-Z0-9_]*)\((?[^)]*std::string [a-zA-Z_][a-zA-Z0-9_]*[^)]*)\)(?\s*:\s*[^{]*?)(?(?[a-zA-Z_][a-zA-Z0-9_]*)\((?[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:** `(?[a-zA-Z_][a-zA-Z0-9_]*)\((?[^)]*?)(?(^|\(|, ))std::string (?[a-zA-Z_][a-zA-Z0-9_]*)(?[^)]*)\)` +**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:** `(?[a-zA-Z_][a-zA-Z0-9_]*)\((?[^)]*?)(?(^|\(|, ))std::(vector|string|unordered_set|unordered_map|set|map)<[^>]+> (?[a-zA-Z_][a-zA-Z0-9_]*)(?[^)]*)\)` +**Replacement:** `${func}(${before}${sep}const std::${2}<${3}>& ${param}${after})` + +Examples: +- `function(std::vector vec)` → `function(const std::vector& vec)` + +## 6. std::move for push_back + +**Pattern:** `(?[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?[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:** `(?template\s*<\s*typename\s+(?[a-zA-Z_][a-zA-Z0-9_]*)\s*>\s*[^(]*\([^)]*?)(?\k) (?[a-zA-Z_][a-zA-Z0-9_]*)(?[^)]*\))` +**Replacement:** `${before}${type}&& ${param}${after}` + +Examples: +- `template void func(T arg)` → `template void func(T&& arg)` + +## 8. std::forward for Perfect Forwarding + +**Pattern:** `(?[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?[a-zA-Z_][a-zA-Z0-9_]*)\)(?=.*template.*\k)` +**Replacement:** `${container}.push_back(std::forward(${param}))` + +Examples: +- In template context: `container.push_back(param)` → `container.push_back(std::forward(param))` + +All these patterns follow modern C++ best practices as requested in the issue. \ No newline at end of file