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 }