D 在类方法中使用委托
我在DMD行为中发现了一些我不理解的东西 我的代码如下所示:D 在类方法中使用委托,d,D,我在DMD行为中发现了一些我不理解的东西 我的代码如下所示: class C1 { private static fun(alias f)() { ; } public static void run() { auto f = delegate bool(int x) {return true;} ; fun!(f)(); return; } } 编译器写入一个错误: Error: template
class C1 {
private static fun(alias f)() {
;
}
public static void run() {
auto f = delegate bool(int x) {return true;} ;
fun!(f)();
return;
}
}
编译器写入一个错误:
Error: template instance fun!(f) cannot use local 'f' as parameter to non-global template fun(alias f)()
因此,我必须在类中创建一个委托字段,使其成为全局的:
class C1 {
private static fun(alias f)() {
;
}
private static bool delegate(int) f;
public static void run() {
f = delegate bool(int x) {return true;} ;
fun!(f)();
return;
}
}
这段代码编译时没有错误。但是我不明白,为什么我们不能在方法中声明委托呢?我没有答案,但是这里有一些不适合评论的想法 错误:模板实例有趣!(f) 无法使用本地“f”作为参数 到非全局模板(别名f)() 您会注意到,实际上有两种方法可以解决此问题。或者像您所做的那样,将“f”转换为非局部变量。或者使模板成为全局模板 这表明将局部模板实例化为局部变量存在一些困难。我猜这意味着这是一个技术/实施挑战,而不是一个实际限制(即,不要这样做,因为…) 更新:J.Miller没有意识到的是alias参数绑定到符号而不是值。在您的情况下,符号f在编译时是已知的,因此此代码确实有效:
class C1 {
public static void run() {
auto f = delegate bool(int x) {return true;} ;
fun!(f)();
return;
}
}
private void fun(alias f)() {
import std.stdio;
writeln(f(3));
}
void main () {
new C1;
C1.run();
}
更新:这个问题并不像我原来想的那么简单。以下是我认为真正发生的事情。正如另一位评论者所指出的,我忘记了别名模板参数允许传入任何类型的符号,甚至是局部变量。在这种情况下,对于函数模板,实例化的模板需要一个指向其上下文(运行的主体)的指针,以便它可以访问作为别名参数传入的那些局部变量(如委托f)。但是,
fun
已经是一个类的静态成员,这意味着它已经有一个上下文指针(静态类上下文)。现在,D编译器的一个已知限制是它不能处理需要两个或更多上下文指针的委托。(这就是为什么在错误消息中显示“非全局”——全局函数模板可以工作,因为它们没有上下文。)
第二个例子之所以有效,是因为f
不再是局部变量;它是一个静态成员。它在run
范围内初始化的事实并不会改变这一点
见以下问题:
f
将确保它可以作为模板参数传递:
// Not a delegate, not a local variable anymore (enum)
enum f = function bool(int x) {return true;};
// "static" == not delegate
static bool f(int x) { return true; }
fun!(f)();
// Or pass it as a literal (inferred to be non-delegate)
fun!((int x) => true);
class C1 {
private static fun(bool delegate(int) f) {
assert(f(1) == true);
}
public static void run() {
auto f = delegate bool(int x) { return true; };
fun(f);
}
}
常规方法可以作为模板参数传递:
class C2 {
private static fun(alias f)() {
assert(f(1) == true);
}
private static bool g(int) {
return true;
}
public static void run() {
fun!(g)();
}
}
或者将其作为常规参数而不是模板参数传递:
// Not a delegate, not a local variable anymore (enum)
enum f = function bool(int x) {return true;};
// "static" == not delegate
static bool f(int x) { return true; }
fun!(f)();
// Or pass it as a literal (inferred to be non-delegate)
fun!((int x) => true);
class C1 {
private static fun(bool delegate(int) f) {
assert(f(1) == true);
}
public static void run() {
auto f = delegate bool(int x) { return true; };
fun(f);
}
}
你的目标是什么?我认为可能有更好的方法。基本上,“f”是一个指向委托的可变本地指针(委托本身有一个上下文指针),因此不能将其作为模板参数传递——这些参数必须在编译时已知。回答您关于目标的问题:我有一个基本的私有方法来获取结构数组。我希望有一组公共方法,基于私有方法,但以某种方式过滤数组。然后我想到了让过滤函数成为私有方法的成员。然后我尝试使这个过滤器函数依赖于公共方法的传入值。我觉得这是个好主意。是的!它应该像常规参数一样传递。这是我搜索的答案。我改变了我对这个错误的看法。请参阅更新的回答您对别名模板参数的看法是正确的。这并不像我一开始想的那么简单。我会更新我的答案。。。谢谢