controllo della funzione di compilazione in c ++

-3

Sto sperimentando con complessi framework FSM. Per uno degli approcci che sto considerando mi piacerebbe avere due tipi di funzione: funzione normale e funzione speciale. Il significato esatto non ha importanza. Voglio avere l'applicazione in fase di compilazione che non ci sia più di una funzione speciale per blocco. Posso giocare con i tipi di funzione (ad esempio, creare azioni speciali per restituire il valore), firme, attributo , template meta-programming, macro wrapper, oggetti funzione ecc.

Ogni blocco è molto semplice solo una semplice sequenza di alcune chiamate di funzione:

{
    funcA();
    funcB();
    ..
    funcC();
}
    
posta zzz777 24.04.2017 - 13:49
fonte

2 risposte

3

Non penso che tu possa farlo comodamente. Stai cercando di implementare la tua lingua su C ++, ma C ++ non ha questo tipo di estensibilità.

La prossima cosa migliore è un'interfaccia fluente. Con un'interfaccia fluente, possiamo codificare una grammatica del nostro design nel sistema di tipi. Non possiamo imporre che venga chiamata solo una funzione speciale per blocco C ++, ma possiamo far sì che venga richiamato solo un metodo speciale nella nostra cascata. Ad esempio:

// Mixin for end() operation
struct can_end {
  auto end() && -> void {}
};

// Mixin for normal methods
template<typename next_state>
struct can_normal {
  auto normal_1() && -> next_state { return {}; }
  auto normal_2() && -> next_state { return {}; }
};

// State after special method: only end and normal methods allowed
struct after_special : can_end, can_normal<after_special> {
  after_special() = default;
  after_special(after_special const&) = delete;
};

// State before special method: end, normal, and special allowed
struct before_special : can_end, can_normal<before_special> {
  before_special() = default;
  before_special(before_special const&) = delete;

  auto special() && -> after_special { return {}; }
};

// Entry point
auto block() -> before_special { return {}; }

Ora possiamo scrivere un metodo a cascata come:

block()
  .normal_1()
  .special()
  .normal_2()
  .end();

Ma sarà impedito di invocare il metodo speciale due volte:

block()
  .special()
  .special()  // type error
  .end();

Eliminando il copy ctor, impediamo l'utilizzo di una variabile temporanea per acquisire lo stato pre-speciale:

auto temp = block();  // compilation error: deleted copy ctor
temp.special();
temp.special().end();

Poiché tutti i metodi prendono un riferimento di rvalue, questo scoraggia anche gli inganni come legare lo stato a un riferimento e quindi invocare il metodo speciale due volte. Ma sono sicuro che il sistema di tipo C ++ ha abbastanza portelli di escape per farlo se sei veramente determinato.

    
risposta data 24.04.2017 - 17:52
fonte
3

Forse ho trascurato qualcosa, ma dati i tuoi severi requisiti sui blocchi dovrebbe essere sufficiente:

#define specialFunction(...) \
    int SPECIAL_FUNCTION_ALREADY_CALLED = 0; \
    specialFunction(__VA_ARGS__)

Il tentativo di chiamare specialFunction due volte nello stesso blocco ridefinirà la variabile, innescando così un errore in fase di compilazione.

main.cpp:6:9: error: redeclaration of 'int SPECIAL_FUNCTION_ALREADY_CALLED'
     int SPECIAL_FUNCTION_ALREADY_CALLED = 0; \
         ^

Avvertenza: non funziona su blocchi annidati, interrompe tutti gli usi della chiamata di funzione come espressione. Ma sembra adattarsi al budget.

    
risposta data 04.05.2017 - 20:05
fonte

Leggi altre domande sui tag