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 }