3

目前,我正在使用Vibe.d制作一个网站,该网站有一个Response用于处理每个请求的类。看起来像这样:

import vibe.d;

void index(HTTPServerRequest req, HTTPServerResponse res)
{
  res.render!("index.dt", req);
}

shared static this()
{
  auto router = new URLRouter;
  router.get("/", &index);

  auto settings = new HTTPServerSettings;
  settings.port = 8080;

  listenHTTP(settings, router);
}

在示例中,我将 a 传递const string "index.dtres.render!方法,但我想传递一个变量:

void render(string action, HTTPServerResponse res) {
  res.render!(action);
}

但我收到以下错误:

Error: variable action cannot be read at compile time

在我打电话的每个地方render,我都对字符串进行了硬编码:

render("foo.dt");

但这并不能让编译器满意。知道我怎样才能完成这项工作吗?

4

2 回答 2

3

你不能。饮食模板在编译期间完全预处理,因此有必要知道饮食模板文件名作为编译时常数。您可以将任意数量的变量参数传递给模板以进行动态处理,但模板文件本身是严格编译时的。

在运行时渲染模板的选项已被多次询问,并且在概念上已获得批准,但并未积极开展工作。

于 2014-04-04T22:28:48.987 回答
3

虽然原则上不可能使用运行时变量(这基本上需要在运行时编译 D 代码),但您可以使用编译时定义的enum常量或模板参数来避免直接使用字符串常量:

void index(string templ)(HTTPServerRequest req, HTTPServerResponse res)
{
    res.render!(templ, req);
}

shared static this()
{
    // ...
    router.get("/", &index!"index.dt");
    // BTW, this special case is equal to
    //router.get("/", staticTemplate!"index.dt");
    // ...
}

或使用enum

enum indexTemplateFile = "index.dt";

void index(HTTPServerRequest req, HTTPServerResponse res)
{
    res.render!(indexTemplateFile, req);
}

enum也可以使用这种使用命名的替代形式:

enum TemplateFile {
    index = "index.dt",
    login = "login.dt"
}

void index(HTTPServerRequest req, HTTPServerResponse res)
{
    res.render!(TemplateFile.index, req);
}

这两种方法也可以结合起来,甚至可以用通常的字符串操作修改常量,只要结果仍然可以在编译时计算(例如,可以std.string.toLower在传递字符串之前调用类似的字符串render) .

于 2014-04-06T06:49:58.237 回答