2015-02-05 8 views
5

Quindi, sto cercando di sostituire il seguente codice (C++ 11):lambda in C++ 03

struct test { 
    const char *n; 
    int i; 

    std::function<int(void)> read; 
    std::function<void(int)> write; 
}; 

#define define_test(n, i, bodyRead, bodyWrite) \ 
    { n, i, []() { bodyRead; }, [](int v) { bodyWrite; } } 

std::initializer_list<test> tests = { 
    define_test("test1", 1, return 1, v = 2), 
    ... 
}; 

con un codice compatibile C++ 03 che dà lo stesso effetto:

struct test { 
    test(const char *_n, int _i, boost::function<int(void)> _read, boost::function<void(int)> _write) { 
     n = _n; 
     i = _i; 
     read = _read; 
     write = _write; 
    } 

    const char *n; 
    int i; 

    boost::function<int(void)> read; 
    boost::function<void(int)> write; 
}; 

#define define_test(n, i, bodyRead, bodyWrite) \ 
    (n, i, []() { bodyRead; }, [](int v) { bodyWrite; }) 

std::vector<test> tests; 
static void init_tests(void) { 
    tests.push_back(define_test("test1", 1, return 1, v = 2)); 
} 

senza dubbio, il C++ Studio 2008 compilatore Visual Express SP1 respinge le espressioni lambda, usare il boost non aiuterebbe neanche, tranne che è stato bind() e la spinta lambda ottenuto, che io non sono esattamente sicuro di come lo farei fallo con questo.

Per elaborare più su questo, voglio essere in grado di utilizzare in questo modo:

using namespace boost::assign; 
static std::vector<test> tests; 
static void init_tests(void) { 
    push_back(tests) 
     define_test(...) 
     ...; 
} 

questo significa che le strutture con funzioni statiche non saranno di grande aiuto sia per esempio:

#define define_test(n, i, bodyRead, bodyWrite) \ 
    struct { 
     static void fn##n(void) { bodyRead; } \ 
     static void fnw##n(int v) { bodyWrite; } \ 
    }; \ 
    (n, i, boost::bind(&fn##n), boost::bind(&fnw##n, boost::placeholders::_1)) 

Questo perché sto scrivendo un sacco di questo e C++ 11 è stato così facile.

+0

temo, siete alla ricerca di convenienza disturbare la manutenzione del codice. (Passando una funzione non banale come parametro macro) –

+0

@ DieterLücking Bene, ho finito per ridisegnare l'intera cosa :(devo amare C++ –

risposta

4

È possibile eseguire il cobble di qualcosa insieme a Boost Phoenix, ad esempio.

sintassi
s_tests.push_back(test ("test1", 1, phx::val(1), phx::ref(v) = arg1*1)); 
s_tests.push_back(test ("test2", 2, phx::val(2), phx::ref(v) = arg1*2)); 

Non raggiungerà naturale C++, ma almeno sarà abbastanza pieno ha caratterizzato (supporta eccezioni, while_, for_, switch_, la gente del posto, bind(), ecc):

Live On Coliru

#include <boost/function.hpp> 

struct test { 
    const char *n; 
    int i; 

    boost::function<int(void)> read; 
    boost::function<void(int)> write; 

    test(char const* n, int i, boost::function<int(void)> read, boost::function<void(int)> write) 
     : n(n), i(i), read(read), write(write) 
    {} 
}; 

#include <boost/phoenix.hpp> 
#include <vector> 
using namespace boost::phoenix::arg_names; 
namespace phx = boost::phoenix; 

namespace mocks { 
    static int v; 

    typedef std::vector<test> test_t; 

    test_t const& tests() { 
     static test_t s_tests; 
     if (s_tests.empty()) 
     { 
      s_tests.push_back(test ("test1", 1, phx::val(1), phx::ref(v) = arg1*1)); 
      s_tests.push_back(test ("test2", 2, phx::val(2), phx::ref(v) = arg1*2)); 
     } 

     return s_tests; 
    } 
} 

#include <iostream> 

int main() { 


    for (mocks::test_t::const_iterator it = mocks::tests().begin(); 
      it != mocks::tests().end(); ++it) 
    { 
     test const& test = *it; 
     std::cout << "'" << test.n << "'\t" << test.i << ", " << test.read() << ", "; 

     test.write(42); 
     std::cout << "mock v: " << mocks::v << "\n"; 
    } 
} 

Stampe

'test1' 1, 1, mock v: 42 
'test2' 2, 2, mock v: 84 
+0

Realizzato il campione ** [veramente live] (http://coliru.stacked-crooked.com/a/3bc8a371eb64c923) ** e prova di C++ 03. (Naturalmente, c'erano molti altri dettagli specifici di C++ 11) – sehe

+0

Scusate se il mio commento era un po 'vago. Diciamo che voglio salvare un po' di digitazione, per esempio '#define define_test (n, i, bodyRead, bodyWrite) (n, i, boost :: phoenix :: val (bodyRead), boost :: phoenix :: ref (v) = boost :: phoenix :: arg_names :: arg1; if_ (v) [bodyWrite;]} 'o forse solo' [bodyWrite;] ' –

+0

Non sono sicuro di cosa stai provando a salvare. Non penso che tu sia in grado di includere" dichiarazioni C++ naturali "direttamente nella tua macro sognata (questo è un po 'il punto di forza di Lambdas) Tuttavia, a mio parere, la Boost Phoenix fa un lavoro abbastanza decente che si avvicina. pagine, o per ripensare alle tue esigenze :) – sehe