Cythonic way to wrap boost::geometry::Point accessors - c++

What is the correct cythonic way to wrap the following member functions of a boost::geometry::Point? The code snippet comes from here.
/// #brief Get a coordinate
/// #tparam K coordinate to get
/// #return the coordinate
template <std::size_t K>
inline CoordinateType const& get() const
{
#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
BOOST_GEOMETRY_ASSERT(m_created == 1);
BOOST_GEOMETRY_ASSERT(m_values_initialized[K] == 1);
#endif
BOOST_STATIC_ASSERT(K < DimensionCount);
return m_values[K];
}
/// #brief Set a coordinate
/// #tparam K coordinate to set
/// #param value value to set
template <std::size_t K>
inline void set(CoordinateType const& value)
{
#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
BOOST_GEOMETRY_ASSERT(m_created == 1);
m_values_initialized[K] = 1;
#endif
BOOST_STATIC_ASSERT(K < DimensionCount);
m_values[K] = value;
}
I first attempted using:
cdef extern from "s57/data/geometries.h" namespace "bg::model":
cdef cppclass _Geo2 "bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree>>":
_Geo2()
_Geo2( const _Geo2& other )
const double get[size_t]() except +
void set[size_t](double) except +
but then I don't know where to go since something like this:
property x:
def __set__(self, double value):
deref(self._p).set[0](value)
gives me this failure:
Error compiling Cython file:
------------------------------------------------------------
...
property x:
def __set__(self, double value):
deref(self._p).set[0](value)
^
------------------------------------------------------------
c:\XXXX\x.pyx:24:31: not parsable as a type
My current working solution has been to create some helper functions like:
double get_geo2_x( geo2& pnt );
double get_geo2_y( geo2& pnt );
void set_geo2_x( geo2& pnt, double value );
void set_geo2_y( geo2& pnt, double value );
Does somebody have in mind a more elegant solution?

You're running into problems with Cython's handling of non-type template parameters. You can manually specify function names using strings, which are inserted directly into the generated C code (see http://docs.cython.org/src/userguide/external_C_code.html#resolving-naming-conflicts-c-name-specifications)
As a very simple example
// example.hpp
#include <iostream>
class C {
template <int K>
void set(double value) {
std::cout << K << ": " << value << std::endl;
}
And the Cython code
cdef extern from "example.hpp":
cdef cppclass C:
void set0 "set<0>"(double) except +
void set1 "set<1>"(double) except +
def do_set():
# very simple illustrative example
cdef C c
c.set0(1.0)
c.set1(1.5)
}
Whenever Cython sees set0 called on a C it substitutes set<0>, calling the template function directly. You can then use properties, as you were trying to do.
This probably isn't significantly better than creating helper functions, but it might be a little easier.

Related

Generate argument names from list of types to forward to another function

I would like to generate a function that forwards its arguments to another function. I know that std::function does it somehow, but I cannot seem to find the right syntax myself.
It would be ok for my usecase to use som kind of template magic, but i want
the user to be able to get information on the calling types when they use the function, like std::function does.
My usecase uses class member functions, so a solution that only works in that context is accepted. I tried to created the smallest example code possible.
#include <iostream>
// Macro usage cannot be changed
#define ARGS int, int
void otherFunction(int x, int y) {
std::cout << x << "," << y << "\n";
}
// This is the behaviour i want
void expectedImplementation(int _1, int _2) {
otherFunction(_1, _2);
}
// This works, but it prevents the user to view the expected
// types in their IDE
template <typename ...Args>
void templateVersion(Args ... args) {
otherFunction(args...);
}
// This is the version I cannot get to work
// It does not need to look like this, but it needs to get
// its argument types from
//void func(ARGS) {
// otherFunction(/*how?*/);
//}
int main() {
expectedImplementation(1, 2);
templateVersion(1, 2);
//func(1, 2);
}
godbolt
How do I accomplish this?
Edit:
The function that needs to be forwarded to is also different for each instance of the function.
Edit 2:
Ok, It seems like it's hard to specify the context without the context. Here is the actual code that I want to generalize. Here Is the template magick stuff where it should fit in. No memory should be used, otherwise I would just use the solution I have now with template parameter packs.
Edit 3:
A better example:
#include <iostream>
#define ARGS int, int
struct Inner {
void otherFunction(int x, int y) {
std::cout << x << y << std::endl;
}
};
struct Wrapper {
Inner inner;
// This works, but it prevents the user to view the expected
// types in their ide
template <typename ...Args>
void templateVersion(Args ... args) {
inner.otherFunction(args...);
}
// The concept I try to figure out
void function(ARGS) { // It does not need to look exactly like this
// , but functionally it needs to be somithing like it
// Forward the arguments to the `ìnner` class
}
};
int main() {
auto wrapper = Wrapper{};
wrapper.templateVersion(10, 20);
}
Your macro ARGS does not define named arguments. You cannot forward the type of unnamed arguments. That's a limitation of the language.
Either forget about using macros, and change your function definiton:
void func(int a, int b) {
otherFunction(a, b);
}
Or change the definition of the macro:
#define ARGS int a, int b
void func(ARGS) {
otherFunction(a, b);
}
That said, nothing beats the template solution. Make sure you use perfect forwarding.
template <typename ...Args>
void templateVersion(Args&& ... args) {
otherFunction(std::forward<Args>(args)...);
}

compiling boost.spirit.karma example, customize_embedded_container.cpp fails

Using gcc or clang latest, boost 1.68 (or 1.69),
Compiling boost.spirit.karma example customize_embedded_container.cpp fails, unless replacing type with value_type in line 26.
The other useful example, customize_use_as_container.cpp also fails, asking for value_type etc. in indirect_iterator,
" no named type 'value_type' in 'std::iterator_traits' "
For the reference, the example : https://www.boost.org/doc/libs/1_69_0/libs/spirit/example/karma/customize_use_as_container.cpp
Any that have a clue or a working example for container-specialisation that is compiling in boost.spirit.karma ?
Given my case, a skeleton for the solution, or rather a workaround just playing with the parts that really works easy in boost.spirit:
namespace X {
struct p { double t,v;};// point, time, value
struct ts { // simplified time-series representation, time-axis computed
bool s;
double t0,dt;size_t n;// ti = t0 + dt*i
std::vector<double> v;// v.size()===n
p point(size_t i ) const { return p{t0+dt*i,v[i]};}
};
//--would like to output grammar like {pfx:(true|false),data:[[t,v]..]}
//--; first construct a container class out of ts, using boost iterator_facade
//--; to get away with few lines.(simplified..)
struct ts_c {
using value_type=p;// iterate over (t,v), t is computed, v is plain vector
ts * c;
struct iterator:public::boost::iterator_facade<iterator,p,boost::random_access_traversal..> { //..
iterator(ts*c,size_t pos=0u):c{c},pos{pos} {}
//.. plain vanilla impl. goes here according to boost::iterator_facade.
private:
ts* c;
size_t pos;
};
using const_iterator=iterator;
iterator begin() const;//.. etc. impl. of need it stuff.
};
}
// use FUSION to adapt the ts-type, let last tuple member return the
// tuple members:
// 0 true if n>0, otherwise false
// 1 true if ts.s is true
// 2 returns a vanilla iterable container, ts_c exposing type p
BOOST_FUSION_ADAPT_ADT(
X::ts,
(bool,bool, obj.n>0,/**/)
(bool,bool,obj.s,/**/)
(X::ts_c,X::ts_c, X::ts_c(&obj),/**/)
)
//-- then combining the boost spirit complex example to emit the point class p
namespace X {
namespace ka=boost::spirit::karma;
/** generate a point like [123.0, 3.14], or [123.0,null] if !isfinite.
* using the complex example pattern given in boost::spirit,
*/
template<class OutputIterator>
struct point_generator:ka::grammar<OutputIterator,p()> {
point_generator():point_generator::base_type(pg) {
using ka::true_;
using ka::bool_;
using ka::omit;
pg =
&true_ <<( '[' << double_<< ',' << double_ << ']')
|
omit[bool_]<< ( '[' << double_<< ',' << "null" << ']')
;
}
ka::rule<OutputIterator,p()> pg;
};
/** #brief a ts generator
*
* outputs:
* {pfx:(true|false),data:[[t,v],..]}
* or if empty
* {pfx:null,data:null}
*/
template<class OutputIterator>
struct ts_generator:ka::grammar<OutputIterator,ts()> {
ts_generator():ts_generator::base_type(tsg) {
using ka::true_;
using ka::bool_;
using ka::omit;
tsg =
&true_ <<"{pfx:"<<bool_<<",data:"<<( '[' << pt_ % ',' << ']')<<'}'
|
omit[bool_]<< "{pfx:null: data:null}"
;
}
ka::rule<OutputIterator,ts()> tsg;
point_generator<OutputIterator> pt_;
};
}

How to use different member variable names in a template?

Edit: Completely rewrote the question to address suggestions in comments
In a large project that I participate in, there are a lot of classes that wrap messages, events, etc. They do not have a common ancestor and were (and still are) written by different people in different groups.
Most of these classes (or structs) have public members indicating error codes and descriptions. However, since they are used mostly within a single group and conventions are pretty loose, some of them name the members errStr, while others use errDesc.
For example:
struct X {
// stuff here...
int errCode;
std::string errStr;
};
struct Y {
// stuff here...
int errCode;
std::string errDesc;
};
I am trying to write a function template that will accept an object and print out the value of the whatever member variable that it has.
In pseudocode:
template<typename T>
bool logError(T const& x)
{
if (x.errCode == 0)
return true;
// if (T::errStr exists)
// log(x.errStr);
// else if (T::errDesc exists)
// log(x.errDesc);
return false;
}
What complicates matters is that the compiler that we use is VS2012, which is not fully C++11 compliant.
I have been messing with std::enable_if, std::is_same, etc for a while and so far the only result is an impressive collection of different compiler errors.
I was pointed to this by #T.C.
While it turned out to work quite well, it appears clunky and I was wondering if it can be simplified, or another solution offered, using the C++11 features that VS2012 supports.
Thank you!
In principle you can use SFINAE to detect the relevant member, but with C++03 (your compiler's standard) this yields complex, verbose code that's easy to break by maintenance – I give a complete example at the end below. The relevant techniques are covered in umpteen places on the web. E.g. I googled "c++ detect data member SFINAE" and hey presto, some GitHub code, and other examples. The ability to find information on the web, including basic googling, is very important to a developer. So, just try it.
An IMO more practical approach – because it's much simpler code that does not introduce maintenance problems and that goes in the direction you want the code to evolve – is to simply define overloads of an accessor function, one per class, like this:
string errorMessageOf( X const& o ) { return o.errStr; }
string errorMessageOf( Y const& o ) { return o.errDsc; }
Not everything needs to be a template.
Ordinary overloads are nice.
Your desired function template is then
template< class Type >
bool logError( Type const& x )
{
if (x.errCode == 0) return true; // A really dangerous thing to do
// Especially in Windows error code 0 a.k.a. NOERROR etc. is
// sometimes returned by GetLastError for a genuine failure. You
// should better treat it as "unknown cause".
clog << errorMessageOf( x ) << endl;
return not clog.fail(); // The return value is unspecified.
}
Example of instead using C++03 SFINAE, with code that works with Visual C++ 2012, and supporting an arbitrary number of names for the error message data member:
#include <iostream>
#include <stddef.h>
#include <string>
//----------------------------------------------- Machinery:
namespace reusable {
typedef ptrdiff_t Size;
template< Size n >
struct SizeCarrier_ { char nPlusOne[n + 1]; };
template< class Type, Type >
struct TypeFrom_;
} // namespace reusable
namespace my{
using std::string;
namespace impl {
using reusable::SizeCarrier_;
using reusable::TypeFrom_;
struct ErrorMsgMemberId { enum Enum{ noSuch, errStrName, errDescName }; };
template< class Type >
class ErrorMsgMemberId_
{
private:
template< class U >
static SizeCarrier_< ErrorMsgMemberId::errStrName >
memberId( TypeFrom_<string U::*, &U::errStr>* );
template< class U >
static SizeCarrier_<ErrorMsgMemberId::errDescName>
memberId( TypeFrom_<string U::*, &U::errDesc>* );
template< class U >
static SizeCarrier_<ErrorMsgMemberId::noSuch>
memberId( ... );
public:
static ErrorMsgMemberId::Enum const value = static_cast<ErrorMsgMemberId::Enum>(
sizeof( memberId< Type >( 0 ).nPlusOne ) - 1
);
};
template< ErrorMsgMemberId::Enum kind >
struct ErrorMsgFunc_;
template<>
struct ErrorMsgFunc_< ErrorMsgMemberId::errStrName >
{
template< class Type >
string operator()( Type const& o ) const
{ return o.errStr; }
};
template<>
struct ErrorMsgFunc_< ErrorMsgMemberId::errDescName >
{
template< class Type >
string operator()( Type const& o ) const
{ return o.errDesc; }
};
} // namespace impl
template< class Type >
string errorMsgOf( Type const& o )
{
static impl::ErrorMsgMemberId::Enum const member_id =
impl::ErrorMsgMemberId_< Type >::value;
return impl::ErrorMsgFunc_< member_id >()( o );
}
} // namespace my
//----------------------------------------------- Example usage:
struct X {
// stuff here...
int errCode;
std::string errStr;
};
struct Y {
// stuff here...
int errCode;
std::string errDesc;
};
struct Z {
// stuff here...
int errCode;
};
int main()
{
X const x = { 1, "X::errStr" };
Y const y = { 2, "Y::errDesc" };
Z const z = { 3 };
using namespace std;
cout << my::errorMsgOf( x ) << endl;
cout << my::errorMsgOf( y ) << endl;
//cout << my::errorMsgOf( z ) << endl; //! Fails with 'noSuch' in message.
}

How to write read-only accessor functions in an aggregate root class?

Overall design: I have an aggregate class C that contains N member variables of type M_i, i = 1 ... N that each have a common write-only update() interface as well as class-specific read-only accessor functions [F]un_i(), [F] = any letter, i = 1 .. N (they do not have such regular names in reality). Each of the member types M_i forms an independent abstraction of its own, and is used elsewhere in my program.
The aggregate class needs to update all the members in a single transaction, so it has an update() function of its own calling the update() member function of all its member variables.
// building blocks M_i, i = 1 ... N
class M_1
{
public:
// common write-only interface
void update();
// M_1 specific read-only interface
int fun_1() const;
// ...
int fun_K() const;
private:
// impl
};
// ...
class M_N
{
public:
// common write-only interface
void update();
// M_N specific read-only interface
int gun_1() const;
// ...
int gun_K() const;
private:
// impl
};
// aggregate containing member variables M_i, i = 1 ... N
class C
{
public:
// update all members in a single transaction
void update()
{
m1_.update();
// ...
mN_.update();
}
// read-only interface?? see below
private:
M_1 m1_;
// ...
M_N mN_;
};
Question: the do I access the various member functions of the various member variables in the aggregate class? I can think of three alternatives:
Alternative 1: write N * K delegates to all K member functions of all N member variables
class C
{
int fun_1() const { return m1_.fun_1(); }
// ...
int fun_K() const { return m1_.fun_K(); }
// ...
int gun_1() const { return mN_.gun_1(); }
// ...
int gun_K() const { return mN_.gun_K(); }
// as before
};
int res = C.fun_5(); // call 5th member function of 1st member variable
Alternative 2: write N accessors to all N member variables
class C
{
M_1 const& m1() const { return m1_; }
// ...
M_N const& mN() const { return mN_; }
// as before
};
int res = C.m1().fun_5(); // call 5th member function of 1st member variable
Alternative 3: write 1 accessor template to all N member variables
class C
{
public:
enum { m1, /* ... */ mN };
template<std::size_t I>
auto get() const -> decltype(std::get<I>(data_))
{
return std::get<I>(data_);
}
private:
std::tuple<M_1, /* ... */ M_N> data_;
};
int res = C.get<m1>().fun_5(); // call 5th member function of 1st member variable
Alternative 1 avoids violating the Law of Demeter but it needs an awful lot of tedious boiler plate code (in my application, N = 5 and K = 3, so 15 delegating wrappers). Alternative 2 cuts down on the number of wrappers, but the calling code feels a little uglier to me. But since all that code is read-only, and modfications can only happen through the consistent aggregate update(), my current opinion that Alternative 2 is preferable to Alternative 1 (and at least safe). If that's the case, then a fortiori, Alternative 3 should be the best choice since it uses only a single accessor and has the same safety guarantees as Alternative 2.
Question: what is the preferred interface for this type of code?
Turning my comment into an answer.
If you decide to go with alternative 1 (N*K delegates), you can use Boost.Preprocessor to do the boilerplate work for you:
#include <boost/preprocessor.hpp>
// Define identifier names
#define FUNCTIONS (fun)(gun)(hun)
#define MEMBER_NAMES (m1_)(m2_)(m3_)
#define SUFFIXES (_1)(_2)(_3)
// Utility "data structure"
// Used to hand down state from iteration over functions to iteration over suffixes
#define WRAP_DATA(function, member) \
(2, (function, member))
#define UNWRAP_DATA_FUNTION(data) \
BOOST_PP_ARRAY_ELEM(0, data)
#define UNWRAP_DATA_MEMBER(data) \
BOOST_PP_ARRAY_ELEM(1, data)
// Accessor-generating functionality
// Convenience macro for generating the correct accessor name
#define CREATE_FUNCTION_NAME(data, suffix) \
BOOST_PP_CAT(UNWRAP_DATA_FUNCTION(data), suffix)
// Macro generating one accessor delegation
#define GENERATE_ACCESSOR(r, data, suffix) \
int CREATE_FUNCTION_NAME(data, suffix) () const { return UNWRAP_DATA_MEMBER(data).CREATE_FUNCTION_NAME(data, suffix) (); }
// Generate accessors
class C
{
// Execute GENERATE_ACCESSOR once for each element of SUFFIXES
#define BOOST_PP_LOCAL_MACRO(iter) \
BOOST_PP_SEQ_FOR_EACH(GENERATE_ACCESSOR, WRAP_DATA(BOOST_PP_SEQ_ELEM(iter, FUNCTIONS), BOOST_PP_SEQ_ELEM(iter, MEMBER_NAMES)), SUFFIXES)
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_SEQ_SIZE(FUNCTIONS) - 1)
// Execute BOOST_PP_LOCAL_MACRO once for each value within BOOST_PP_LOCAL_LIMITS
#include BOOST_PP_LOCAL_ITERATE()
// rest of class C here
// ...
};
Translated into pseudo-code to better highlight the working logic:
FUNCTIONS = {fun, gun, hun};
MEMBER_NAMES = {m1_, m2_, m3_};
SUFFIXES = {_1, _2, _3};
struct Data {
auto function, member;
};
auto createFunctionName(data, suffix) {
return data.function + suffix;
}
auto generateAccessor(data, suffix) {
return "int " + createFunctionName(data, suffix) + "() const { return " + data.member + "." + createFunctionName(data, suffix) + "(); }";
}
class C
{
for (i = 0; i < sizeof(FUNCTIONS); ++i) {
foreach (suffix in SUFFIXES) {
generateAccessor(Data(FUNCTIONS[i], MEMBER_NAMES[i]), suffix);
}
}
};
One other possibility is
int func(int i, int j); // i,j can be enums as well..
Though you need to decide if this makes sense for you. You would need to write a huge nested switch inside though, but the interface is simpler.
This method is ideal of course if you can store your objects in an array, and all member functions are part of a common interface of M_i types.
I would completely separate the update behaviour from the single element functionalities. All the M_i classes should implement an Updatable interface that simply contains the update method.
This allows you to safely expose N accessors to (non const) Updatable interfaces.
class Updatable{
public:
virtual void update() = 0;
} ;
class M_i : public Updatable{
public:
void update();
};
Given the aggregate class C you can then:
expose N accessor to the const M_i classes
ask for the Updatable interface of a given M_i class. By accessing this (non-const) reference you can safely issue updates to any of the M_i instances.
call the delegate update directly.
.
class C{
public:
/** Returns the updatable interface related to M_1 */
Updatable& getM_1Updater(){ return M_1}
/** Returns the const reference to M_1*/
const M_1& getM_1() const { return M_1}
/** delegates update to each contained element */
void update(){
m1.update();
m2.update();
[...]
}
};
The solution that gives you the best user friendly code with compile time resolution of calls has to rely on templates.
Indeed, if you want to be able to call fun(i,j) (actually fun<i,j>()) where i is an index to a member variable, and j an index to a member function of this variable, then you have to define the mappings. Both mappings.
First mapping between the member variable index and the variable itself, that implies a mapping between the member variable index and the variable type.
Second mapping between the member function index and the member function itself. However, as this mapping depend on the type of the indexed member variable, it has to be defined for every combination. You cannot provide the user a completely indexed solution without defining this mapping. Or the other way round: if you don't want the caller to bother about the type of the i-th variable to know what is the name of the j-th function he wants to call (that depends on the type of the i-th variable), then you have to provide the mappings.
With this, the user will be able to call int v = c.fun<i, j>() without the knowledge of neither the type of the i-th variable, neither the name of the j-th function for this i-th variable.
template <typename M, int K> int fun(M const & m) const;
template <> int fun<M_1, 1>(M_1 const & m) const { return m.fun_1(); }
template <> int fun<M_1, 2>(M_1 const & m) const { return m.fun_2(); }
template <> int fun<M_1, 3>(M_1 const & m) const { return m.fun_3(); }
template <> int fun<M_2, 1>(M_2 const & m) const { return m.fun_1(); }
template <> int fun<M_2, 2>(M_2 const & m) const { return m.fun_2(); }
template <> int fun<M_2, 3>(M_2 const & m) const { return m.fun_3(); }
...
class C
{
// Define the specialized class type for every N
template <int N> class Mi { typedef void M; };
template <> class Mi<1> { typedef M_1 M; };
template <> class Mi<2> { typedef M_2 M; };
template <> class Mi<3> { typedef M_3 M; };
// Define the function to get the member N
template <int N> Mi<N>::M const & get_M() const;
template <> Mi<1>::M const & get_M() { return m1; } const;
template <> Mi<2>::M const & get_M() { return m2; } const;
template <> Mi<3>::M const & get_M() { return m3; } const;
// Define the member function to call member N, function K
template <int N, int K>
int fun() { return fun<Mi<N>::M, K>( get_M<N>(); }
};
Now, if you want that the user can make calls with i and j as run-time variables, then this is not the way to go. Prefer an int fun(i, j) function with lots of if and switch. You cannot have both.

C++ preprocessor concatenation

I have a function build with function pointers. I think it might be faster to try to exchange this function with pre processor macro. At least, I would like to try out the macro so I can measure if it generates faster code.
It's more or less like this:
typedef int (Item::*GetterPtr)(void)const;
typedef void (Item::*SetterPtr)(int);
void doStuff(Item* item, GetterPtr getter, SetterPtr setter, int k)
{
int value = (item->*getter)();
// .. Do some stuff
(item->*setter)(newValue);
}
And it's called like
// ...
doStuff(&item, &Item::a, &Item::setA, _a);
doStuff(&item, &Item::b, &Item::setB, _b);
doStuff(&item, &Item::c, &Item::setC, _c);
// ...
I think it might be possible to swap this with something like:
#define DO_STUFF(item, getter, setter, k) do { \
int value = item ## -> ## getter ## (); \
//... \
item ## -> ## setter ## (newValue); \
} while(0);
but it gives me errors like:
error: pasting ")" and "setA" does not give a valid preprocessing token
There's a way to concatenate the function names and it's object?
It is better to use inline functions than macros. Using any good compiler, this will give you the same efficiency as the macro, but with added type checking and debug symbols if you need them.
Token-pasting means "combining two tokens to form a single token".
You don't want that. ptr_to_item->a() isn't one token. Assuming ptr_to_item is a variable name, it's 5: ptr_to_item, ->, a, (, ).
Your macro should just be:
#define DO_STUFF(item, getter, setter, k) do { \
int value = (item)->getter(); \
//... \
(item)->setter(newValue); \
} while(0);
By the way, for the macro haters, this avoids macros while also avoiding the use of a pointer-to-member-function as a function parameter. It could be tried if the macro is faster than the questioner's function due to the call through a pointer not being inlined. I don't know if/when it will make a difference:
#include <iostream>
struct A {
int f;
int foo() {return f;}
void setfoo(int a) { f = a; }
};
template <typename T, typename U, U (T::*GETTER)(), void (T::*SETTER)(U)>
void doit(T &obj, U k) {
U value = (obj.*GETTER)();
value += k;
(obj.*SETTER)(value);
}
int main() {
A a = {0};
std::cout << a.foo() << "\n";
doit<A,int,&A::foo, &A::setfoo>(a,1);
std::cout << a.foo() << "\n";
doit<A,int,&A::foo, &A::setfoo>(a,2);
std::cout << a.foo() << "\n";
}
Because it's there.
There's at least one weakness. U can't be a reference type in the template. But since it's effectively fixed as int in the code in the question, the template parameter U may not be needed at all, so hopefully that isn't too limiting.
Member pointers are generally ungood for efficiency. They're also ungood for safety, because there's a loophole in the C++ type system regarding accessibility.
Instead of your current design for doStuff like ...
typedef int (Item::*GetterPtr)(void)const;
typedef void (Item::*SetterPtr)(int);
void doStuff(Item* item, GetterPtr getter, SetterPtr setter, int k)
{
int value = (item->*getter)();
// .. Do some stuff
(item->*setter)(newValue);
}
//...
doStuff(&item, &Item::a, &Item::setA, _a);
doStuff(&item, &Item::b, &Item::setB, _b);
doStuff(&item, &Item::c, &Item::setC, _c);
... consider ...
int foo( int value )
{
// .. Do some stuff
return newValue;
}
//...
item.setA( foo( item.a() ) );
item.setB( foo( item.b() ) );
item.setC( foo( item.c() ) );
Getting rid of the setter/getter-design for the Item class will probably simplify things even more. Anyway, I recommend that you try re-designing. For that, keep in mind the responsibilites of an Item instance, and what knowledge it needs for that.
Cheers & hth.,
– Alf