2015-02-05 13 views
5

Więc staram się zastąpić następujący kod C++ (11):lambda w 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), 
    ... 
}; 

C++ z kodem 03 kompatybilnym który daje ten sam efekt:

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)); 
} 

Bez wątpienia kompilator Visual C++ Studio 2008 Express SP1 odrzuca wyrażenia lambda, użycie boost też by nie pomogło, z wyjątkiem funkcji bind() i boostu lambda, którego nie jestem do końca pewny, w jaki sposób zrób to z tym.

Aby opracować więcej na ten temat, chcę być w stanie wykorzystać tak:

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

to znaczy kodowanym z funkcji statycznych nie będzie zbyt pomocne albo np

#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)) 

To dlatego, że piszę tonę tego i C++ 11 było tak łatwe.

+0

boję, szukasz wygody niepokojące zachowanie kodu. (Przekazanie nietrywialnej funkcji jako parametru makro) –

+0

@ DieterLücking Cóż, skończyłem na przeprojektowaniu tego wszystkiego :(muszę pokochać C++ –

Odpowiedz

4

Możesz na przykład spleść coś razem z Boost Phoenix.

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)); 

Nie będzie osiągnąć naturalny C++ składni, ale przynajmniej będzie dość pełny funkcjonalny (obsługuje wyjątki, while_, for_, switch_, mieszkańców, bind() itd.):

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"; 
    } 
} 

Drukuje

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

Wykonałem próbkę ** [naprawdę żyję] (http://coliru.stacked-crooked.com/a/3bc8a371eb64c923) ** i C++ 03 proof. (Oczywiście było wiele innych szczegółów specyficznych dla C++ 11). – sehe

+0

Przepraszam, jeśli mój komentarz był trochę niejasny. Załóżmy, że chcę zapisać niektóre np. '#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;]} 'lub może po prostu' [bodyWrite;] ' –

+0

Nie jestem pewien, co piszesz, próbujesz zapisać.Nie sądzę, że będziesz w stanie uwzględnić" naturalne instrukcje C++ "bezpośrednio w twoich wymarzonych makrach (jest to swego rodzaju punkt sprzedaży lambdas), ale moim zdaniem, Boost Phoenix robi całkiem przyzwoitą robotę, zbliżając się do siebie. strony lub przemyśleć swoje wymagania :) – sehe

Powiązane problemy