2013-02-06 9 views
12

Pracuję nad systemem wbudowanym, więc rozmiar kodu jest problemem. Używanie standardowej biblioteki podnosi mój rozmiar binarny o około 60k, z 40k do 100k. Chciałbym użyć funkcji std ::, ale nie mogę tego uzasadnić dla 60k. Czy istnieje samodzielna implementacja, której mogę użyć lub coś podobnego? Używam go do domyślnego rzucania lambdami w funkcje członkowskie z powiązanymi zmiennymi w języku C++ 11.Czy istnieje samodzielna implementacja funkcji std ::?

+1

próbowałeś boost :: funkcję i boost :: wiążą? – juanchopanza

+0

@juanchopanza: Czy ma zmniejszyć rozmiar kodu wrt 'std :: function'? –

+0

Czy rozważałeś użycie innej biblioteki C++, np. Dinkumware? – nneonneo

Odpowiedz

9

60k pochodzi z obsługi wyjątków dodawanych przez kompilator, ponieważ wyjątki były wymagane dla funkcji std ::. std :: function rzuca tylko jeden wyjątek, "bad_function_call". Usunąłem więc kod, który wyrzucił wyjątek, teraz usuwa błędy, jeśli wywoływana jest pusta funkcja, a ja zaoszczędziłem sobie 60 tys.

+9

Twój kompilator prawdopodobnie ma opcję zamiany wyrażeń 'throw' na wywołania na' std :: terminate() '(lub jakiś jego wariant). – GManNickG

+1

+1 do smaru do kolan. Wywołał u mnie uśmiech. – Potatoswatter

+0

Tylko do porównania. Jaki jest teraz całkowity rozmiar binarny? –

8

Oto prosta implementacja szablonu szablonu typu std :: function bez uwzględniania jakichkolwiek nagłówków. Można dostosować zachowanie, jak chcesz (jak przenieść/do przodu, pusty odpowiedź połączeń, etc):

live_demo

// Scroll down for example of usage 
namespace bicycle 
{ 
    template<typename Result,typename ...Args> 
    struct abstract_function 
    { 
     virtual Result operator()(Args... args)=0; 
     virtual abstract_function *clone() const =0; 
     virtual ~abstract_function() = default; 
    }; 

    template<typename Func,typename Result,typename ...Args> 
    class concrete_function: public abstract_function<Result,Args...> 
    { 
     Func f; 
    public: 
     concrete_function(const Func &x) 
      : f(x) 
     {} 
     Result operator()(Args... args) override 
     { 
      return f(args...); 
     } 
     concrete_function *clone() const override 
     { 
      return new concrete_function{f}; 
     } 
    }; 

    template<typename Func> 
    struct func_filter 
    { 
     typedef Func type; 
    }; 
    template<typename Result,typename ...Args> 
    struct func_filter<Result(Args...)> 
    { 
     typedef Result (*type)(Args...); 
    }; 

    template<typename signature> 
    class function; 

    template<typename Result,typename ...Args> 
    class function<Result(Args...)> 
    { 
     abstract_function<Result,Args...> *f; 
    public: 
     function() 
      : f(nullptr) 
     {} 
     template<typename Func> function(const Func &x) 
      : f(new concrete_function<typename func_filter<Func>::type,Result,Args...>(x)) 
     {} 
     function(const function &rhs) 
      : f(rhs.f ? rhs.f->clone() : nullptr) 
     {} 
     function &operator=(const function &rhs) 
     { 
      if((&rhs != this) && (rhs.f)) 
      { 
       auto *temp = rhs.f->clone(); 
       delete f; 
       f = temp; 
      } 
      return *this; 
     } 
     template<typename Func> function &operator=(const Func &x) 
     { 
      auto *temp = new concrete_function<typename func_filter<Func>::type,Result,Args...>(x); 
      delete f; 
      f = temp; 
      return *this; 
     } 
     Result operator()(Args... args) 
     { 
      if(f) 
       return (*f)(args...); 
      else 
       return Result{}; 
     } 
     ~function() 
     { 
      delete f; 
     } 
    }; 
} 

// ___________________[ Example of usage ]___________________ // 

int func1(double) 
{ 
    return 1; 
} 
struct Functor2 
{ 
    int operator()(double) 
    { 
     return 2; 
    } 
}; 

double func3(bool,int) 
{ 
    return 3.0; 
} 
struct Functor4 
{ 
    double operator()(bool,int) 
    { 
     return 4.0; 
    } 
}; 

int main() 
{ 
    int res = 10; 
    { 
     bicycle::function<int(double)> f{func1}; 

     res -= f(1.0); 
     f = Functor2{}; 
     res -= f(2.0); 
    } 
    { 
     bicycle::function<double(bool,int)> f1; 
     f1 = func3; 

     bicycle::function<double(bool,int)> f2{f1}; 
     res -= f2(true,1); 

     f1 = Functor4{}; 
     f2 = f1; 
     res -= f2(false,2); 
    } 
    return res; 
} 
+0

Privet Evgeny, niesamowita implementacja, ale jak to działa? dlaczego funkcja jest zdefiniowana z jednym ogólnym , a następnie zdefiniowana na nowo przy użyciu 2 parametrów , po cichu nie rozumiem zasad pisania takiego kodu :) – barney