When an output range's put method only accepts elements of type T, use the global put to handle outputting a T[] to the range or vice-versa.
import std.traits : isSomeChar; static struct A { string data; void put(C)(C c) if (isSomeChar!C) { data ~= c; } } static assert(isOutputRange!(A, char)); auto a = A(); put(a, "Hello"); assert(a.data == "Hello");
put treats dynamic arrays as array slices, and will call popFront on the slice after an element has been copied.
Be sure to save the position of the array before calling put.
int[] a = [1, 2, 3], b = [10, 20]; auto c = a; put(a, b); assert(c == [10, 20, 3]); // at this point, a was advanced twice, so it only contains // its last element while c represents the whole array assert(a == [3]);
It's also possible to put any width strings or characters into narrow strings -- put does the conversion for you.
Note that putting the same width character as the target buffer type is nothrow, but transcoding can throw a std.utf.UTFException.
// the elements must be mutable, so using string or const(char)[] // won't compile char[] s1 = new char[13]; auto r1 = s1; put(r1, "Hello, World!"w); assert(s1 == "Hello, World!");
Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.
In this table "doPut" is a method that places e into r, using the correct primitive: r.put(e) if R defines put, r.front = e if r is an input range (followed by r.popFront()), or r(e) otherwise.
Tip: put should not be used "UFCS-style", e.g. r.put(e). Doing this may call R.put directly, by-passing any transformation feature provided by Range.put. put(r, e) is prefered.