Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I not concatenate a const(char)* to a string in D?

The code

string bar = "Hello ";
const(char) * foo = "world!";
bar ~= foo;

fails to compile in the third line. Why? What elegant alternatives do I have?

The error output is Error: cannot append type const(char)* to type string.

like image 611
Ralph Tandetzky Avatar asked Aug 11 '12 10:08

Ralph Tandetzky


2 Answers

Don't use a const(char)*?

string bar = "Hello ";
string foo = "world!";
bar ~= foo;

String literals in D are of type string, you shouldn't ever need to use a const(char)*, except when interfacing with C code.

The reason D doesn't allow that concatenation is because const(char)* isn't a string, in any sense of the word. Strings in D are immutable(char)[] (which is alias'd by string). A const(char)* is just a pointer to a constant character. Unlike C and C++, there is no implied null-terminator, so D can't and won't assume there is one.

If for whatever reason you absolutely must use a const(char)* and you know that it is null terminated, then you can make a const(char)[] out of it by slicing, which you can then append to a string:

string bar = "Hello ";
const(char)* foo = "world!";
bar ~= foo[0..strlen(foo)];
like image 178
Peter Alexander Avatar answered Oct 08 '22 18:10

Peter Alexander


string is an alias for immutable(char)[], i.e., a mutable slice of immutable characters. bar in your code is an array slice of this type.

The relationship between const(char)* and string literals in D is just that string literals are always null terminated, and typed as either immutable(char)[] (i.e. string), or immutable(char)* for convenient interoperability with C code; the latter being implicitly convertible to const(char)*. It's important to note that this is only the case for string literals: arrays are not necessarily null terminated in the general case, and they are not implicitly convertible to their pointer equivalent (though the member .ptr of any slice T[] is of type T* and points to the first element of the slice).

The concatenation operators work with arrays as well as user-defined types with the relevant operator overloads, and nothing else. As D does not allow overloading of operators for inbuilt types, it's not possible to make them work with pointers.

The solution is to make a slice of the string the pointer points to, by using the slice operator which works on arrays and pointers alike:

import core.stdc.string : strlen;

string bar = "Hello ";
const(char)* foo = "world!";
bar ~= foo[0 .. strlen(foo)];

In the above, the expression foo[0 .. strlen(foo)] is of type const(char)[], which can be concatenated with bar, which is of type immutable(char)[] (i.e. string).

like image 37
jA_cOp Avatar answered Oct 08 '22 16:10

jA_cOp