[labmda & function] strange assembly errors with an unsupported compiler

Hi All, This is an anomaly I experienced with Portland Group C++ compiler. Well OK, Boost doesn't support this compiler... But so far for Lambda and Function libraries I was able to run all of the tests in the 1-33-1 distribution with success, and it seems pgCC is doing a real good job. There is this one exception though: pgCC generates assembly errors on this arguably weird code that I have. gcc, msvc and hpCC worked fine... So obviously this seems to be an issue for PG itself and not Boost; but the code under question is really a bit weird and I am not 100% sure if it is correct use of boost or even C++. Before I carry on with bug reports to PG I'd like to ask for your suggestions on it... Here is the code. Briefly, a boost::function is being passed to some function template that expects a functor to apply on its second argument. Another level of indirection is added where the boost::function itself is generated from a lambda expression inside another function. I wasn't able to narrow it down any further.. (highlighted code is here: http://rafb.net/p/28TknK25.html) (compiler error messages follow) // ======================================== #include <boost/function.hpp> #include <boost/lambda/lambda.hpp> #include <boost/lambda/bind.hpp> #include <boost/lambda/casts.hpp> #include <iostream> // Some struct of only double members struct A { double a; double b; }; // The "complicated" function that expect a functor to // operate on an instance of A template< class Func > void foo(const Func& f, const A& a) { std::cout << f(a) << std::endl; } // A function object generator. // It returns a functor which in turn returns some // double member of A accessed via address offset boost::function<double(const A&)> getmem ( const A* obj, const double* mem ) { ptrdiff_t shift = mem - reinterpret_cast<const double*>(obj); using namespace boost::lambda; return *(ll_reinterpret_cast<const double*>(&_1) + constant(shift) ); } // int main() { A obj; obj.a = 1.; obj.b = 2.; // foo( getmem(&obj, &obj.b), obj ); return 0; } // wherever this compiles, it prints out "2". // ========================================== Here is the compiler output: PGCC-W-0155-No va_start() seen (/opt/pgi/6.1.4/linux86-64/6.1/include/CC/iostream: 689) PGCC/x86 Linux/x86-64 6.1-4: compilation completed with warnings /tmp/pgCCbaaaasxqap.s: Assembler messages: /tmp/pgCCbaaaasxqap.s:2499: Error: junk `(%rbx)' after expression /tmp/pgCCbaaaasxqap.s:2500: Error: junk `(%rbx)' after expression The assembly lines under question is pasted here: http://rafb.net/p/LW5IX765.html -- lines 7 and 8. The va_start() warning is probably irrelevant (this is not the only place I have seen it, and never failed before with these warnings) any guidance will be appreciated, thanks -- Server Levent Yilmaz Mechanical Engineering @ PITT

Server Levent Yilmaz wrote:
// A function object generator. // It returns a functor which in turn returns some // double member of A accessed via address offset boost::function<double(const A&)> getmem ( const A* obj, const double* mem ) { ptrdiff_t shift = mem - reinterpret_cast<const double*>(obj); using namespace boost::lambda; return *(ll_reinterpret_cast<const double*>(&_1) + constant(shift) ); }
This definitely sounds like a compiler bug. But your code isn't quite standard-conforming. You ought to use a pointer to member, not reinterpret_cast tricks. boost::function<double(const A&)> getmem( double A::* pm ) { return pm; }
int main() { A obj; obj.a = 1.; obj.b = 2.; // foo( getmem(&obj, &obj.b), obj );
foo( getmem( &A::b ), obj );
}

On 1/7/07, Peter Dimov <pdimov@mmltd.net> wrote:
Server Levent Yilmaz wrote:
This definitely sounds like a compiler bug. But your code isn't quite standard-conforming. You ought to use a pointer to member, not reinterpret_cast tricks.
Hi Peter, My concerns about the sample code not being quite right was actually not this reinterpret_casts (though, I do agree that they are a bit fishy -- please see next paragraph). I was worried about temporary lambda expressions and function objects being carried around to other scopes. I can not quite see if this valid or not.. As a side discussion, well it is kind of off topic but now that you brought it up, there was a case where I couldn't get away with using member pointers and needed this pointer algebra. I'd appreciate any idea on this. The problem is simple. Take this struct, struct A { double a[3]; } For, this I needed to callback, say, a[2]. A callback facility designed with member pointers wouldn't be able to handle this case. Right? -- Server Levent Yilmaz Mechanical Engineering @ PITT

Server Levent Yilmaz wrote:
As a side discussion, well it is kind of off topic but now that you brought it up, there was a case where I couldn't get away with using member pointers and needed this pointer algebra. I'd appreciate any idea on this. The problem is simple. Take this struct,
struct A { double a[3]; }
For, this I needed to callback, say, a[2]. A callback facility designed with member pointers wouldn't be able to handle this case. Right?
You are right, there is no way to take a member pointer to a[2]. You need int main() { A obj = { 1, 2, 3 }; namespace ll = boost::lambda; boost::function<double(const A&)> f = ll::bind( &A::a, ll::_1 )[ 2 ]; foo( f, obj ); }
participants (2)
-
Peter Dimov
-
Server Levent Yilmaz