Skip to content

Commit 0e2e5ba

Browse files
konardclaude
andcommitted
Implement modern C++ style improvements for issue #58
Add comprehensive regex patterns to improve generated C++ code quality: **Type Style Improvements:** - Fix reference positioning: `Type &val` → `Type& val` - Fix pointer positioning: `Type *val` → `Type* val` **Performance Optimizations:** - Add std::move for constructor parameters: `field(string)` → `field(std::move(string))` - Convert function parameters to const references: `func(std::string param)` → `func(const std::string& param)` - Add std::move to container insertions: `vector.push_back(value)` → `vector.push_back(std::move(value))` **Template Enhancements:** - Use universal references: `template<typename T> func(T arg)` → `template<typename T> func(T&& arg)` - Add perfect forwarding: `push_back(param)` → `push_back(std::forward<decltype(param)>(param))` Updated both C# and Python implementations to maintain consistency. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent ae39a45 commit 0e2e5ba

File tree

4 files changed

+168
-0
lines changed

4 files changed

+168
-0
lines changed

csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,25 @@ public class CSharpToCppTransformer : TextTransformer
634634
// AppDomain.CurrentDomain.ProcessExit -= OnProcessExit;
635635
// /* No translation. It is not possible to unsubscribe from std::atexit. */
636636
(new Regex(@"AppDomain\.CurrentDomain\.ProcessExit -= ([a-zA-Z_][a-zA-Z0-9_]*);"), "/* No translation. It is not possible to unsubscribe from std::atexit. */", 0),
637+
// C++ Modern Style Improvements
638+
// std::string &val
639+
// std::string& val
640+
(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),
641+
// Type *val
642+
// Type* val
643+
(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),
644+
// constructor(std::string string) : field(string)
645+
// constructor(std::string string) : field(std::move(string))
646+
(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),
647+
// function(std::string param)
648+
// function(const std::string& param)
649+
(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),
650+
// function(std::vector<Type> param)
651+
// function(const std::vector<Type>& param)
652+
(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),
653+
// vector.push_back(value)
654+
// vector.push_back(std::move(value)) for non-const value parameters
655+
(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),
637656
}.Cast<ISubstitutionRule>().ToList();
638657

639658
/// <summary>
@@ -752,6 +771,14 @@ public class CSharpToCppTransformer : TextTransformer
752771
// \n\n}
753772
// \n}
754773
(new Regex(@"\r?\n[ \t]*\r?\n(?<end>[ \t]*})"), Environment.NewLine + "${end}", 10),
774+
// C++ Universal Reference and std::forward for templates
775+
// template<typename T> void func(T arg)
776+
// template<typename T> void func(T&& arg)
777+
(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),
778+
// Inside template functions, use std::forward for perfect forwarding
779+
// container.push_back(templateParam)
780+
// container.push_back(std::forward<decltype(templateParam)>(templateParam))
781+
(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),
755782
}.Cast<ISubstitutionRule>().ToList();
756783

757784
/// <summary>

python/cs2cpp/cs2cpp.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,25 @@ def __init__(
633633
# AppDomain.CurrentDomain.ProcessExit -= OnProcessExit;
634634
# /* No translation. It is not possible to unsubscribe from std::atexit. */
635635
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),
636+
# C++ Modern Style Improvements
637+
# std::string &val
638+
# std::string& val
639+
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),
640+
# Type *val
641+
# Type* val
642+
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),
643+
# constructor(std::string string) : field(string)
644+
# constructor(std::string string) : field(std::move(string))
645+
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),
646+
# function(std::string param)
647+
# function(const std::string& param)
648+
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),
649+
# function(std::vector<Type> param)
650+
# function(const std::vector<Type>& param)
651+
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),
652+
# vector.push_back(value)
653+
# vector.push_back(std::move(value)) for non-const value parameters
654+
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),
636655
]
637656

638657

@@ -745,4 +764,12 @@ def __init__(
745764
# \n\n}
746765
# \n}
747766
SubRule(r"\r?\n[ \t]*\r?\n(?P<end>[ \t]*})", "\n\g<end>", max_repeat=10),
767+
# C++ Universal Reference and std::forward for templates
768+
# template<typename T> void func(T arg)
769+
# template<typename T> void func(T&& arg)
770+
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),
771+
# Inside template functions, use std::forward for perfect forwarding
772+
# container.push_back(templateParam)
773+
# container.push_back(std::forward<decltype(templateParam)>(templateParam))
774+
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),
748775
]

test_improvements.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using Platform.RegularExpressions.Transformer.CSharpToCpp;
3+
4+
class TestProgram
5+
{
6+
static void Main()
7+
{
8+
var transformer = new CSharpToCppTransformer();
9+
10+
// Test 1: Type& val style
11+
string input1 = "void function(std::string &value) { }";
12+
string result1 = transformer.Transform(input1);
13+
Console.WriteLine("Test 1 - Type& val style:");
14+
Console.WriteLine($"Input: {input1}");
15+
Console.WriteLine($"Output: {result1}");
16+
Console.WriteLine();
17+
18+
// Test 2: Type* val style
19+
string input2 = "void function(int *pointer) { }";
20+
string result2 = transformer.Transform(input2);
21+
Console.WriteLine("Test 2 - Type* val style:");
22+
Console.WriteLine($"Input: {input2}");
23+
Console.WriteLine($"Output: {result2}");
24+
Console.WriteLine();
25+
26+
// Test 3: const& for string parameters
27+
string input3 = "void function(std::string value) { }";
28+
string result3 = transformer.Transform(input3);
29+
Console.WriteLine("Test 3 - const& for string parameters:");
30+
Console.WriteLine($"Input: {input3}");
31+
Console.WriteLine($"Output: {result3}");
32+
Console.WriteLine();
33+
34+
// Test 4: std::move for push_back
35+
string input4 = "vector.push_back(value);";
36+
string result4 = transformer.Transform(input4);
37+
Console.WriteLine("Test 4 - std::move for push_back:");
38+
Console.WriteLine($"Input: {input4}");
39+
Console.WriteLine($"Output: {result4}");
40+
Console.WriteLine();
41+
}
42+
}

verification_examples.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# C++ Style Improvements Verification
2+
3+
This document shows the transformations our regex patterns should perform:
4+
5+
## 1. Type Reference Style (Type& val instead of Type &val)
6+
7+
**Pattern:** `(?<type>std::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) &(?<var>[a-zA-Z_][a-zA-Z0-9_]*)`
8+
**Replacement:** `${type}& ${var}`
9+
10+
Examples:
11+
- `std::string &value``std::string& value`
12+
- `MyType &ref``MyType& ref`
13+
14+
## 2. Type Pointer Style (Type* val instead of Type *val)
15+
16+
**Pattern:** `(?<type>std::[a-zA-Z0-9_]+|[a-zA-Z][a-zA-Z0-9_]*) \*(?<var>[a-zA-Z_][a-zA-Z0-9_]*)`
17+
**Replacement:** `${type}* ${var}`
18+
19+
Examples:
20+
- `int *pointer``int* pointer`
21+
- `std::string *ptr``std::string* ptr`
22+
23+
## 3. Constructor std::move Pattern
24+
25+
**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_]*)\))`
26+
**Replacement:** `${constructor}(${params})${init}${field}(std::move(${param}))`
27+
28+
Examples:
29+
- `MyClass(std::string str) : field(str)``MyClass(std::string str) : field(std::move(str))`
30+
31+
## 4. Const Reference for std::string Parameters
32+
33+
**Pattern:** `(?<func>[a-zA-Z_][a-zA-Z0-9_]*)\((?<before>[^)]*?)(?<sep>(^|\(|, ))std::string (?<param>[a-zA-Z_][a-zA-Z0-9_]*)(?<after>[^)]*)\)`
34+
**Replacement:** `${func}(${before}${sep}const std::string& ${param}${after})`
35+
36+
Examples:
37+
- `function(std::string param)``function(const std::string& param)`
38+
- `method(int x, std::string str)``method(int x, const std::string& str)`
39+
40+
## 5. Const Reference for Container Parameters
41+
42+
**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>[^)]*)\)`
43+
**Replacement:** `${func}(${before}${sep}const std::${2}<${3}>& ${param}${after})`
44+
45+
Examples:
46+
- `function(std::vector<int> vec)``function(const std::vector<int>& vec)`
47+
48+
## 6. std::move for push_back
49+
50+
**Pattern:** `(?<container>[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?<value>[a-zA-Z_][a-zA-Z0-9_]*)\)(?!\s*//.*const)`
51+
**Replacement:** `${container}.push_back(std::move(${value}))`
52+
53+
Examples:
54+
- `vector.push_back(value)``vector.push_back(std::move(value))`
55+
56+
## 7. Universal Reference for Templates
57+
58+
**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>[^)]*\))`
59+
**Replacement:** `${before}${type}&& ${param}${after}`
60+
61+
Examples:
62+
- `template<typename T> void func(T arg)``template<typename T> void func(T&& arg)`
63+
64+
## 8. std::forward for Perfect Forwarding
65+
66+
**Pattern:** `(?<container>[a-zA-Z_][a-zA-Z0-9_]*)\.push_back\((?<param>[a-zA-Z_][a-zA-Z0-9_]*)\)(?=.*template.*\k<param>)`
67+
**Replacement:** `${container}.push_back(std::forward<decltype(${param})>(${param}))`
68+
69+
Examples:
70+
- In template context: `container.push_back(param)``container.push_back(std::forward<decltype(param)>(param))`
71+
72+
All these patterns follow modern C++ best practices as requested in the issue.

0 commit comments

Comments
 (0)