Naturalnie tak jak w temacie sie nie da, to tylko duze streszczenie problemu.
Stanalem dzisiaj przed takim zadaniem, i nie wiem czy mi na mozg padlo od pracowania na co dzien w C#, czy tez tworcy boost::mem_fn ten fakt przeoczyli..
zalozmy:
struct X
{
int value;
int meth(){ return (value = 1); }
int const_meth() const { return value; }
};
potrzebuje utworzyc kontener ktory bedzie w stanie przechowywac wyniki otrzymane przez aplikowanie boost::mem_fn na zarowno const- jak i non-const member function. funktory z tego kontenera pozniej beda pobierane i odpalane na obiekcie NONconst
...
container<X> parts; //typ skrocony, patrz nizej
parts.push_back( boost::mem_fn( &X::meth) );
...
...
X nonconst;
parts[0](&nonconst);
container moze byc vector<>, cokolwiek (formalny typ w takim przypadku to vector<boost::mf0<int, X>> )
problem pojawia sie gdy... ktos sprobuje wcisnac do kontenera
parts.push_back( boost::mem_fn( &X::const_meth) );
poniewaz const_meth jest const, wiec mem_fn zwraca cmf0<>
i tu moje zdziwienie - brak jest zdefiniowanej konwersji pomiedzy cmf0 -> mf0. w druga strone, sie nie dziwie, ale w tę? boost::remove_const etc przylozone na typie metody const_meth nie daja efektu, poniewaz to nie o top-level-const chodzi, tylko o parametr metody (X const *this const [problematyczny vs. toplevelconst]). mozna sobie poradzic type- albo reintepret-castem:
parts.push_back( boost::mem_fn( (int(X::*)())&X::const_meth) );
parts.push_back( boost::mem_fn( reinterpret_cast<int(X::*)()>(&X::const_meth)) );
[btw. co tymbardziej dowodzi ze to nie jest widziane jako problem const, tylko typu wlasciwego, gdyz inaczej reinterpret by nie przeszedl!]
ale jest to raz, ze brzydkie, dwa ze IMHO nadmiarowe jak cholera, trzy - klient klasy kontenera nie chce tego robic, on chce po prostu wrzucac wskazniki na metody.. bo przeciez do wolania na non-const obiekcie nie wazne czy metoda jest const czy nie, cztery - std::vector/list/stack/etc nie bede edytowac..
pytanie do Was: czy przeoczylem jakis naglowek, i gdzies jest schowana konwersja z cmf0->mf0, czy przeoczylem cos cholernie waznego i w ogolnosci nie mam prawa tego probowac robic, czy tez to dziura w typach zwracanych boost::mem_fn
ps. nie moge przejsc na boost::bind, ani ::function, ani ::bind, poniewaz ich typy zwracane maja sizeof() > sizeof(void*)
ps2. naglowki metod sa 100% standardowe i znane - int(T::)() oraz int(T::)()const, i zadne inne, zadne nie sa free functions, zadne static, zadne virtual i nigdy takie nie beda (raczej:))
ps3. oczywiscie sizeof(cmf0<...>) == sizeof(mf0<...>), wiec moge sobie nawet na chama sam napisac konwersje bajt-po-bajcie bo w srodku jest zawsze jeden raw pointer, ale nie o to przeciez chodzi w problemie typow..