While other, more elegant solutions can be better used, if you can, string mixins can be extremely useful. They allow you to use both code reuse and code generation. They are checked at compile time. The code that is the result is exactly the same as if you yourself wrote it yourself, so it is no less secure than if you yourself wrote it.
The problem with string mixins is that they are harder to control than manually written code in the sense that it is not physically placed in your source identically with line numbers that are clearly traceable to errors, and can be harder to debug. For example, take the hello world with a string mixin:
import std.stdio; void main() { mixin(hello()); } string hello() { return " writeln(\"hello world\"); "; }
If we removed the semicolon after writeln() , then the resulting error would be
dd(7): found 'EOF' when expecting ';' following statement
The mixin is executed on line 5. Line 7 is an empty line. So the line number has limited utility here. Now this mixin is short enough so that we can put it on one line and get it to say that the error was on the same line as mixin, but with more complex mixins, which obviously will not work. Thus, using a combination of strings, your ability to determine where the error is broken. If the code was generated using CTFE, then it would be much harder to figure out what exactly the code looks like to figure out what is wrong with it. This is very similar to what code turns into a C-style macro, except that it can be worse because they can be generated rather than a direct replacement. However, they do not replace, unless you explicitly specify them, so they are much safer than C-style macros.
String mixins are absolutely safe and nothing really bad with them, but they make maintenance more difficult in some way. Corresponding handwritten code will be easier to debug. However, streaming mixins are powerful enough that they can do a lot of code generation for you and save you a lot of support costs in this sense, and they allow you to reuse the code, which can also be a big boost.
Thus, regardless of whether the string uses mixin, a good idea in a particular situation depends on that situation. I don’t see anything special in them, and of course I would not call them an anti-pattern, but there are pros and cons to using them so that they are a good idea, it depends on what you do, In many cases there are more elegant, cleaner solutions that would be better. In others, this is exactly what the doctor ordered.
Personally, I think that they are fantastic if you want to generate code, eliminating the need to write this code manually and, possibly, simplify the creation of the correct code for various situations and avoid the risk of creating new errors, as, for example, you wrote it yourself in each from the places where you used mixin. It is also one way to simply reuse code without having to worry about the cost of a function call or problems with unidirectional constraints or anything else that makes code reuse more difficult to call functions or inheritance. You simply copy and paste the code in each place so that when you change the code, the changes are correctly inserted everywhere, without the need to worry about tracking them all, as if you had a manual copy and pasted.
So, use string mixins if necessary, and it's probably best not to use them if you don't need them, but there is nothing wrong with using them.