diff --git a/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp.Tests/CSharpToCppTransformerTests.cs b/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp.Tests/CSharpToCppTransformerTests.cs index edca381..effb349 100644 --- a/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp.Tests/CSharpToCppTransformerTests.cs +++ b/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp.Tests/CSharpToCppTransformerTests.cs @@ -35,5 +35,69 @@ public static void Main(string[] args) var actualResult = transformer.Transform(helloWorldCode); Assert.Equal(expectedResult, actualResult); } + + [Fact] + public void BigTypeParametersTest() + { + // Test a simple case first - just std::string + const string code = @"void function(std::string name)"; + var transformer = new CSharpToCppTransformer(); + var actualResult = transformer.Transform(code); + + // Check that std::string becomes const std::string& + Assert.Contains("const std::string& name", actualResult); + } + + [Fact] + public void UniversalReferenceParametersTest() + { + const string code = @"void function(auto&& param) +{ + // body +}"; + const string expectedResult = @"void function(auto&& param) +{ + // body +};"; + var transformer = new CSharpToCppTransformer(); + var actualResult = transformer.Transform(code); + Assert.Equal(expectedResult, actualResult); + } + + [Fact] + public void StdForwardTest() + { + const string code = @"void function(auto&& param) +{ + list.push_back(param); +}"; + const string expectedResult = @"void function(auto&& param) +{ + list.push_back(std::forward(param)); +};"; + var transformer = new CSharpToCppTransformer(); + var actualResult = transformer.Transform(code); + Assert.Equal(expectedResult, actualResult); + } + + [Fact] + public void MixedParameterTypesTest() + { + const string code = @"void function(std::vector list, big_type case1, const big_type& case2, auto&& case3) +{ + list.push_back(case1); + list.push_back(case2); + list.push_back(case3); +}"; + const string expectedResult = @"void function(const std::vector& list, const big_type& case1, const big_type& case2, auto&& case3) +{ + list.push_back(std::forward(case1)); + list.push_back(std::forward(case2)); + list.push_back(std::forward(case3)); +};"; + var transformer = new CSharpToCppTransformer(); + var actualResult = transformer.Transform(code); + Assert.Equal(expectedResult, actualResult); + } } } diff --git a/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs b/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs index 2f5dceb..1bab361 100644 --- a/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs +++ b/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs @@ -647,6 +647,12 @@ public class CSharpToCppTransformer : TextTransformer // IDisposable disposable) // IDisposable &disposable) (new Regex(@"(?I[A-Z][a-zA-Z0-9]+(<[^>\r\n]+>)?) (?[_a-zA-Z0-9]+)(?,|\))"), "${argumentAbstractType} &${argument}${after}", 0), + // std::vector list) or std::string name) or MyClass obj) -> const std::vector& list) or const std::string& name) or const MyClass& obj) + // Convert big types to const references for better performance + (new Regex(@"(?std::(vector|string|map|set|list|unordered_map|unordered_set|multimap|multiset|deque|array|queue|stack|priority_queue)<[^>\r\n]*>|std::(string|wstring)|[A-Z][a-zA-Z0-9]*(<[^>\r\n]+>)?) (?[_a-zA-Z0-9]+)(?,|\))"), "const ${bigType}& ${argument}${after}", 5), + // auto&& param) -> auto&& param) (keep universal references as is) + // This rule preserves universal references for perfect forwarding + (new Regex(@"(?auto&&) (?[_a-zA-Z0-9]+)(?,|\))"), "${universalRef} ${argument}${after}", 0), // ICounter c1; // ICounter* c1; (new Regex(@"(?I[A-Z][a-zA-Z0-9]+(<[^>\r\n]+>)?) (?[_a-zA-Z0-9]+)(? = null)?;"), "${abstractType} *${variable}${after};", 0), @@ -741,6 +747,10 @@ public class CSharpToCppTransformer : TextTransformer // \Anamespace (new Regex(@"(\A)(\r?\n)+namespace"), "$1namespace", 0), // \A \n ... class + // Transform universal reference parameters to use std::forward + // For parameters declared as auto&& that are passed to functions, use std::forward + // push_back(param) where param is auto&& -> push_back(std::forward(param)) + (new Regex(@"(?push_back|emplace_back|insert|emplace)\((?[_a-zA-Z0-9]+)\)(?=\s*(;|,|\)))"), "${method}(std::forward(${param}))", 0), // \Aclass (new Regex(@"(\A)(\r?\n)+class"), "$1class", 0), // \n\n\n