2015-08-30 1 views
0

К моему явному восторгу я обнаружил, что D достиг прогресса и теперь фактически работает на Windows 64 бит. У него даже есть интеграция с Visual Studio, которая, кажется, работает, насколько я могу видеть после нескольких часов игры с моей новой игрушкой.Письменные функции, соответствующие шаблонам определенных функций прототипов

Таким образом, очевидно, что я только начал играть с D как язык, и я кровавый новичок в D.

В коде ниже моей целью было определить прототипы функций в шаблоне, а затем писать функции как суб -функции main(), которые соответствуют этим прототипам. Но компилятор жалуется, и прямо сейчас я не могу понять, как правильно это сделать (возможно, простая проблема синтаксиса).

Ошибки компилятора я получаю:

main.d(90): Error: function main.Actor!(int, int).Worker (Duration timeout, bool function(int) timeoutHandler, bool function(int, int) messageHandler, int context) is not callable using argument types()

main.d(90): Error: function main.main.W1OnTimeout (int context) is not callable using argument types()

main.d(90): Error: function main.main.W1OnMessage (int context, int message) is not callable using argument types()

Building Debug\ConsoleApp1.exe failed!

import std.stdio; 
import core.time; 
import std.socket; 
import std.concurrency; 
import core.thread; 

enum SystemMessage 
{ 
    Shutdown, 
    Terminate, 
    Ping, 
    Enable, 
    Disable 
} 

template Actor(C,M) 
{ 
    // TimeoutHandler implementations always return true 
    // unless the worker shall terminate. 
    alias TimeoutHandler = bool function(C); 
    // MessageHandler implementations always return true 
    // unless the worker shall terminate. 
    alias MessageHandler = bool function(C,M); 

    void 
    Worker 
     (Duration timeout 
     , TimeoutHandler timeoutHandler 
     , MessageHandler messageHandler 
     , C context 
     ) 
    { 
     bool running = true; 
     bool enabled = true; 
     while(running) 
     { 
      if(true == std.concurrency.receiveTimeout 
        (timeout, 
        (M message) 
        { 
         if(enabled) 
         { 
          if(!messageHandler(context,message)) 
          { 
           running = false; 
          } 
         } 
        }, 
        (SystemMessage message) 
        { 
         switch(message) 
         { 
          case SystemMessage.Shutdown: running = false; break; 
          case SystemMessage.Terminate: running = false; break; 
          case SystemMessage.Enable: enabled = true; break; 
          case SystemMessage.Disable: enabled = false; break; 
          case SystemMessage.Ping: /* TODO: supervisor... */; break; 
          default: break; 
         } 
        } 
        )) 
      { 
      } 
      else 
      { 
       if(!timeoutHandler(context)) 
       { 
        running = false; 
       } 
      } 
     } 
    } 
} 

alias IntIntActor = Actor!(int,int); 


int main(string[] argv) 
{ 
    // The signatures of the next 2 functions conform to the function 
    // declarations, given in Actor template (IntIntActor). 
    // How to write them so it works? 
    bool W1OnTimeout(int context) 
    { 
     writeln("W1OnTimeout()"); 
     return true; 
    } 
    bool W1OnMessage(int context,int message) 
    { 
     writefln("W1OnMessage: context = %d, message = %d", context, message); 
     return true; 
    } 
    // Do I need some special syntax here? Like e.g. &W1OnTimeout ? Or a cast? 
    auto w1 = spawn(IntIntActor.Worker,1000.msecs,W1OnTimeout,W1OnMessage,1); 
    for(int i = 0; i < 10; i++) 
    { 
     send(w1,i); 
    } 
    Thread.sleep(5000.msecs); 
    send(w1,SystemMessage.Shutdown); 
    thread_joinAll(); 
    return 0; 
} 

Спасибо за вашу помощь, заранее!

ответ

3

Вы очень много дали ответ на ваш комментарий:

// Do I need some special syntax here? Like e.g. &W1OnTimeout ? Or a cast? 

&W1OnTimeout точно его; также &IntIntActor.Worker и &W1OnMessage.

Он по-прежнему не компилируется, потому что &W1OnTimeout и &W1OnMessage считаются делегатами, но Worker принимает указатели на функции. Отметьте вложенные функции static и она работает:

static bool W1OnTimeout(int context) 
{ 
    ... 
} 
static bool W1OnMessage(int context,int message) 
{ 
    ... 
} 

В качестве альтернативы, определить их за пределами основной.

+0

Создание их статических и добавление & все еще производит 1 ошибку (то же самое, что и те, что я получил раньше). – BitTickler

+0

Woops, я упомянул '& W1OnTimeout' дважды и пропустил' & IntIntActor.Worker'. Все трое нуждаются в '&'. Отредактировал ответ. – user5282325

+0

Окей - для рабочего был скупой - так как основное внимание уделялось двум не-лямбда-функциям :) Как это будет работать для делегатов (где я мог бы пройти в закрытии)? – BitTickler