只是浏览digitalmars.D.learn论坛和StackOverflow上与D相关的问题,在我看来,初学者D程序员(包括我)的一个主要错误点是char,wchar,dchar的使用和能力的差异,以及相关的字符串类型.这会导致以下问题:
我知道它必须是出于向后兼容性的原因和对来自C++或C的开发人员的熟悉程度,但我认为可以提出一个相当令人信服的论点,即当这些开发人员尝试一些非平凡的事情时,这些可能的收益会被这些问题所抵消.使用char或string并期望它在C/C++中工作,只是让它以难以调试的方式失败.
为了避免很多这些问题,我已经看到D开发社区的有经验的成员一次又一次地告诉没有经验的编码人员使用dchar来避免这样的问题,这就引出了为什么char不是32位的问题默认情况下为unicode字符,将8位ASCII字符降级为achar或类似名称,仅在必要时才触及?
我试图想出一种确定给定符号是否是函数模板的有效方法.下列:
import std.traits: isSomeFunction;
auto ref identity(T)(auto ref T t) { return t; }
static assert(isSomeFunction!identity);
Run Code Online (Sandbox Code Playgroud)
identity
在实例化之前,仍然会失败,因为它仍然是模板.目前我正在使用一个依赖于<template function symbol>.stringof
以某种方式格式化的事实的hack :
//ex: f.stringof == identity(T)(auto ref T t)
template isTemplateFunction(alias f)
{
import std.algorithm: balancedParens, among;
enum isTemplateFunction = __traits(isTemplate, f)
&& f.stringof.balancedParens('(', ')')
&& f.stringof.count('(') == 2
&& f.stringof.count(')') == 2;
}
//Passes
static assert(isTemplateFunction!identity);
Run Code Online (Sandbox Code Playgroud)
我想知道除了hacky stringof
解析之外是否有更好的方法来做到这一点.
使用DMD 2.057,我无法获得以下代码进行编译:
import std.stdio;
import std.array;
enum direction
{
test1,
test2,
test3
}
string getDescriptionOnConnect(direction d)
{
string descriptionOnConnect = "Going in direction %dir%";
foreach(s; __traits(allMembers, direction))
{
if (identifier(d) == s)
{
descriptionOnConnect =
replace(descriptionOnConnect, "%dir%", identifier(d));
}
}
return descriptionOnConnect;
}
int main(string[] argv)
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Error: undefined identifier identifier
虽然在http://www.d-programming-language.org/traits.html#identifier的文档中明确定义了此关键字,但我收到了错误.我也尝试过__identifier
,但我得到了同样的错误.这还没有实现吗?
我正在尝试使用切片运算符从std.range获取take函数的返回值的切片.我的代码:
auto tempChunk = ['a', 'b', 'c', 'd'];
auto a = tempChunk.take(3);
writeln(a[0..2]);
Run Code Online (Sandbox Code Playgroud)
作为Take!R在这种情况下只是char []的别名,我希望这可以编译.但是,编译器告诉我Take!(char[]) cannot be sliced with []
.再举一个例子:
int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
auto s = arr.take(5);
writeln(s[0..4]);
Run Code Online (Sandbox Code Playgroud)
这将编译并运行没有问题,打印[1,2,3,4,5].在这一点上我完全感到困惑,为什么第一个例子不起作用,而第二个例子不起作用.
我最近在阅读关于D中的结构和类的这篇文章,并且作者一度评论说
...这是结构的完美候选者.原因是它只包含一个成员,一个指向ALLEGRO_CONFIG的指针.这意味着我可以无需小心地传递值,因为它只是指针的大小.
这让我思考; 真的是这样吗?我可以想到一些情况,其中相信你正在"免费"传递一个结构可能会有一些隐藏的陷阱.
请考虑以下代码:
struct S
{
int* pointer;
}
void doStuff(S ptrStruct)
{
// Some code here
}
int n = 123;
auto s = S(&n);
doStuff(s);
Run Code Online (Sandbox Code Playgroud)
当s传递给doStuff()时,是否有一个指针(包含在结构中)真正传递给函数的所有东西?在我的脑海中,似乎也会传递任何指向成员函数的指针,以及结构的类型信息.
当然,这不是类的问题,因为它们总是引用类型,但是结构的值语义传递向我表明,如上所述的任何额外的"隐藏"数据将被传递给函数以及struct的指针指向int.这可能导致程序员认为他们正在绕过一个(假设一个64位机器)8字节指针,当他们实际传递一个8字节指针,加上其他几个8字节指向函数时,加上对象的typeinfo是多少字节.然后,粗心的程序员在堆栈上分配的数据远远超过预期.
我在这里追逐阴影,或者在传递带有单个引用的结构时这是一个有效的问题,并认为你得到的结构是伪引用类型?D中是否有一些机制可以防止这种情况发生?
string reverse(string str) pure nothrow
{
string reverse_impl(string temp, string str) pure nothrow
{
if (str.length == 0)
{
return temp;
}
else
{
return reverse_impl(str[0] ~ temp, str[1..$]);
}
}
return reverse_impl("", str);
}
Run Code Online (Sandbox Code Playgroud)
据我所知,这段代码应该进行尾调用优化,但我不知道DMD是否正在这样做.哪个D编译器支持尾调用优化,他们会在这个函数上执行吗?
我有以下代码:
\nProcess proc;\ntry\n{\n ProcessBuilder procBuilder = new ProcessBuilder(/* some args */);\n proc = procBuilder.start();\n if (proc.waitFor(30000, TimeUnit.MILLISECONDS))\n {\n //Etc...\n }\n else\n {\n //Handle it\n }\n}\ncatch (InterruptedException ie)\n{\n currentThread().interrupt();\n}\nfinally\n{\n //What goes here?\n}\n
Run Code Online (Sandbox Code Playgroud)\n我试图找到一些来源来指示是否需要调用proc.destroy()
\xc2\xa0(我应该isAlive()
在调用 destroy 之前检查吗?),并手动关闭其输入/输出/错误流,但无济于事。据我所知,甚至官方文档也没有明确说明这一点。
当我完成生成的进程时,是否有必要执行这些操作,或者只是良好的做法?
\n我正在使用DMD 2.062 for x86.
module test;
private enum test1
{
one,
two,
three,
}
private enum test2
{
one,
two,
three,
}
auto ct = cartesianProduct([EnumMembers!test1], [EnumMembers!test2]);
unittest
{
import std.stdio;
foreach (n, m; ct)
{
writeln(n, " ", m);
}
}
Run Code Online (Sandbox Code Playgroud)
该程序打印出来:
one one
two one
three one
Run Code Online (Sandbox Code Playgroud)
然后抛出访问冲突错误.我是否错误地使用了cartesianProduct,或者这是函数中的错误?
我有一些非常简单的代码拒绝编译:
struct Wrapper(T)
{
T t;
bool opEquals(inout(Wrapper) other) inout
{
return t == other.t;
}
bool opEquals(inout(T) val) inout
{
return t == val;
}
}
struct Test
{
bool opEquals(Test t)
{
return true;
}
}
void main()
{
Wrapper!Test a, b;
assert(a == b);
//Error: inout method Test.opEquals is not
//callable using a mutable object
assert(a == Test());
}
Run Code Online (Sandbox Code Playgroud)
现在,我知道问题,这是Test
没有定义的问题inout
opEquals
.但是,定义另一个可变版本的opEquals
in Test
不能解决这个问题,因为编译器只是忽略它并且inout
无论如何调用版本.有没有办法让我解决这个问题,而不需要opEquals
为mutable 定义一个重载const
,和immutable …
以下代码无法编译:
assert("(((())))()()()()))".count!(c => c.among!('(', ')')) > 0);
Run Code Online (Sandbox Code Playgroud)
带有错误消息:
"Error: template std.algorithm.searching.count cannot deduce function from argument types !((c) => c.among!('(', ')'))(string), candidates are..."
Run Code Online (Sandbox Code Playgroud)
但是[标准库(http://dlang.org/phobos/std_algorithm_searching.html#.count)清楚地表明存在一个count
带谓词的重载,计算R
谓词返回true的所有元素.那么为什么编译器会在我尝试使用count
这种方式时抱怨?
我是C++文件io的新手,所以前几天我决定编写一个小程序,只读取一个UTF-8编码的字符串和一个二进制文件中的配对浮点数.模式是字符串浮点数,没有额外的数据或对之间的间距.编辑我已根据几个答案修改了代码.但是,输出保持不变("RoommateAp 0");
string readString (ifstream* file)
{
//Get the length of the upcoming string
uint16_t stringSize = 0;
file->read(reinterpret_cast<char*>(&stringSize), sizeof(char) * 2);
//Now that we know how long buffer should be, initialize it
char* buffer = new char[stringSize + 1];
buffer[stringSize] = '\0';
//Read in a number of chars equal to stringSize
file->read(buffer, stringSize);
//Build a string out of the data
string result = buffer;
delete[] buffer;
return result;
}
float readFloat (ifstream* file)
{
float buffer = …
Run Code Online (Sandbox Code Playgroud)