1 module it.cpp.function_;
2 
3 import it;
4 
5 @("ref basic param")
6 unittest {
7     shouldCompile(
8         Cpp(
9             q{
10                 void fun(int& i);
11                 void gun(double& i);
12             }
13         ),
14         D(
15             q{
16                 int i;
17                 fun(i);
18                 static assert(!__traits(compiles, fun(4)));
19 
20                 double d;
21                 gun(d);
22                 static assert(!__traits(compiles, gun(33.3)));
23 
24             }
25         ),
26    );
27 }
28 
29 @("ref struct param")
30 unittest {
31     shouldCompile(
32         Cpp(
33             q{
34                 struct Foo { int i; double d; };
35                 void fun(Foo& f);
36             }
37         ),
38         D(
39             q{
40                 auto f = Foo(2, 33.3);
41                 fun(f);
42                 static assert(!__traits(compiles, fun(Foo(2, 33.3))));
43             }
44         ),
45    );
46 }
47 
48 
49 @("ref basic return")
50 unittest {
51     shouldCompile(
52         Cpp(
53             q{
54                 int& fun();
55                 double& gun();
56             }
57         ),
58         D(
59             q{
60                 auto i = fun();
61                 static assert(is(typeof(i) == int), typeof(i).stringof);
62 
63                 auto d = gun();
64                 static assert(is(typeof(d) == double), typeof(i).stringof);
65             }
66         ),
67    );
68 }
69 
70 @("ref struct return")
71 unittest {
72     shouldCompile(
73         Cpp(
74             q{
75                 struct Foo { int i; };
76                 Foo& fun();
77             }
78         ),
79         D(
80             q{
81                 auto f = fun();
82                 static assert(is(typeof(f) == Foo), typeof(i).stringof);
83             }
84         ),
85    );
86 }
87 
88 
89 @("parameter.std.string.rename")
90 @safe unittest {
91     shouldCompile(
92         Cpp(
93             q{
94                 namespace std {
95                     template <typename CharT>
96                     struct basic_string {};
97 
98                     // naming it string clashes with D's immutable(char)[] alias
99                     using mystring = basic_string<char>;
100                 }
101 
102                 struct Foo {
103                     // the parameter used to get translated as
104                     // basic_string without a template parameter
105                     void fun(const std::mystring&);
106                 };
107             }
108         ),
109         D(
110             q{
111                 auto foo = Foo();
112             }
113         ),
114    );
115 }
116 
117 
118 @("parameter.std.string.original.nousing")
119 @safe unittest {
120     shouldCompile(
121         Cpp(
122             q{
123                 namespace std {
124                     template<typename CharT>
125                     struct char_traits;
126 
127                     template<typename T>
128                     struct allocator;
129 
130                     template <typename CharT, typename Traits = std::char_traits<CharT>, typename Allocator = std::allocator<CharT>>
131                     struct basic_string {};
132 
133                     using string = basic_string<char>;
134                 }
135 
136                 struct String {
137                     const std::string& value();
138                 };
139 
140                 void fun(const std::string&);
141             }
142         ),
143         D(
144             q{
145                 auto str = String();
146                 fun(str.value);
147                 auto dstr = "hello";
148                 static assert(!__traits(compiles, fun(dstr)));
149             }
150         ),
151    );
152 }
153 
154 
155 @("parameter.std.string.original.using")
156 @safe unittest {
157     shouldCompile(
158         Cpp(
159             q{
160                 namespace std {
161                     template<typename CharT>
162                     struct char_traits;
163 
164                     template<typename T>
165                     struct allocator;
166 
167                     template <typename CharT, typename Traits = std::char_traits<CharT>, typename Allocator = std::allocator<CharT>>
168                     struct basic_string {};
169 
170                     using string = basic_string<char>;
171                 }
172 
173                 /**
174                    When this test was written, adding the using
175                    directive caused the translation to go from
176                    `string` (wrong) to `basic_string!char` (probably
177                    not what we want but at least doesn't use the alias
178                    for immutable(char)[]).
179                  */
180                 using namespace std;
181 
182                 struct String {
183                     const string& value();
184                 };
185 
186                 void fun(const string&);
187             }
188         ),
189         D(
190             q{
191                 auto str = String();
192                 fun(str.value);
193 
194                 string_ cppstr;
195                 fun(cppstr);
196 
197                 auto dstr = "hello";
198                 static assert(!__traits(compiles, fun(dstr)));
199             }
200         ),
201    );
202 }
203 
204 
205 
206 @ShouldFail("Cannot currently handle templated opBinary. See dpp.translation.function_.functionDecl FIXME")
207 @("opBinary")
208 @safe unittest {
209     shouldCompile(
210         Cpp(
211             q{
212                 struct Foo {
213                     template<typename T>
214                     int operator+(const T& other);
215                 };
216             }
217         ),
218         D(
219             q{
220                 auto foo = Foo();
221                 int ret = foo + 42;
222             }
223         ),
224    );
225 }
226 
227 
228 @("opIndex")
229 @safe unittest {
230     shouldCompile(
231         Cpp(
232             q{
233                 struct Foo {
234                     int operator[](int i);
235                 };
236             }
237         ),
238         D(
239             q{
240                 auto foo = Foo();
241                 int ret = foo[42];
242             }
243         ),
244    );
245 }
246 
247 
248 @("opOpAssign")
249 @safe unittest {
250     shouldCompile(
251         Cpp(
252             q{
253                 struct Foo {
254                     void operator+=(int i);
255                 };
256             }
257         ),
258         D(
259             q{
260                 auto foo = Foo();
261                 foo += 42;
262             }
263         ),
264    );
265 }
266 
267 
268 @("opBang")
269 @safe unittest {
270     shouldCompile(
271         Cpp(
272             q{
273                 struct Foo {
274                     bool operator!() const;
275                 };
276             }
277         ),
278         D(
279             q{
280                 auto foo = Foo();
281                 bool maybe = !foo;
282             }
283         ),
284    );
285 }