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                     // this gets translated as `string` despite the usual
134                     // alias to `immutable(char)[]`
135                     using string = basic_string<char>;
136                 }
137 
138                 struct String {
139                     const std::string& value();
140                 };
141 
142                 void fun(const std::string&);
143             }
144         ),
145         D(
146             q{
147                 auto str = String();
148                 fun(str.value);
149                 auto dstr = "hello";
150                 static assert(!__traits(compiles, fun(dstr)));
151             }
152         ),
153    );
154 }
155 
156 
157 @("parameter.std.string.original.using")
158 @safe unittest {
159     shouldCompile(
160         Cpp(
161             q{
162                 namespace std {
163                     template<typename CharT>
164                     struct char_traits;
165 
166                     template<typename T>
167                     struct allocator;
168 
169                     template <typename CharT, typename Traits = std::char_traits<CharT>, typename Allocator = std::allocator<CharT>>
170                     struct basic_string {};
171 
172                     using string = basic_string<char>;
173                 }
174 
175                 /**
176                    When this test was written, adding the using
177                    directive caused the translation to go from
178                    `string` (wrong) to `basic_string!char` (probably
179                    not what we want but at least doesn't use the alias
180                    for immutable(char)[]).
181                  */
182                 using namespace std;
183 
184                 struct String {
185                     const string& value();
186                 };
187 
188                 void fun(const string&);
189             }
190         ),
191         D(
192             q{
193                 auto str = String();
194                 fun(str.value);
195                 auto dstr = "hello";
196                 static assert(!__traits(compiles, fun(dstr)));
197             }
198         ),
199    );
200 }
201 
202 
203 
204 @ShouldFail("Cannot currently handle templated opBinary. See dpp.translation.function_.functionDecl FIXME")
205 @("opBinary")
206 @safe unittest {
207     shouldCompile(
208         Cpp(
209             q{
210                 struct Foo {
211                     template<typename T>
212                     int operator+(const T& other);
213                 };
214             }
215         ),
216         D(
217             q{
218                 auto foo = Foo();
219                 int ret = foo + 42;
220             }
221         ),
222    );
223 }
224 
225 
226 @("opIndex")
227 @safe unittest {
228     shouldCompile(
229         Cpp(
230             q{
231                 struct Foo {
232                     int operator[](int i);
233                 };
234             }
235         ),
236         D(
237             q{
238                 auto foo = Foo();
239                 int ret = foo[42];
240             }
241         ),
242    );
243 }
244 
245 
246 @("opOpAssign")
247 @safe unittest {
248     shouldCompile(
249         Cpp(
250             q{
251                 struct Foo {
252                     void operator+=(int i);
253                 };
254             }
255         ),
256         D(
257             q{
258                 auto foo = Foo();
259                 foo += 42;
260             }
261         ),
262    );
263 }
264 
265 
266 @("opBang")
267 @safe unittest {
268     shouldCompile(
269         Cpp(
270             q{
271                 struct Foo {
272                     bool operator!() const;
273                 };
274             }
275         ),
276         D(
277             q{
278                 auto foo = Foo();
279                 bool maybe = !foo;
280             }
281         ),
282    );
283 }