Alan Conway escribió:
Manuel Teira wrote:
Some new info about this problem.

I was not able to exactly reproduce the issue with an stanalone and
meaninfull source, but have found a way to pass the compilation (other
than commenting everything, of course). The problem, I think, is related
with the std::lower_bound invocation, as shown before:

"/opt/SUNWspro/prod/include/CC/stlport4/stl/_algo.h", line 491:
Information: Instantiating
std::__lower_bound<qpid::Range<qpid::framing::SequenceNumber>*,
                                 qpid::framing::SequenceNumber,
                                 std::less<qpid::framing::SequenceNumber>,
                                 long>
(qpid::Range<qpid::framing::SequenceNumber>*,
qpid::Range<qpid::framing::SequenceNumber>*,
const qpid::framing::SequenceNumber&,
std::less<qpid::framing::SequenceNumber>,
long*).

All the pain begins (I think) with the fact that the first template type
(the iterator) is not valid to travel through the value type. And this
is produced (I guess) by the call, in RangeSet<T>::addRange(const
Range<T> &r) :

typename Ranges::iterator i =
       std::lower_bound(ranges.begin(), ranges.end(), r.begin());

That way, we are passing two valid Range<T>::iterator types and a T
value. changing that with:

typename Ranges::iterator i = std::lower_bound(ranges.begin(),
ranges.end(), r);

it passes the compilation with the Sun Studio 12.

Hum. Odd. The point of lower_bound(i,j,x) is to evaluate *i < x.
Range<T> has an operator< for T but not for Range<T> so I don't understand
how solaris is satisfying *i < x. when x is a Range<T>

I tried the same thing myself and the GNU compiler didn't choke either so there
clearly is some conversion sequence that allows the < comparison but it doesn't
give the right answer because the RangeSet unit tests fail.

HOWEVER: the simple and obvious step of adding:

     bool operator<(const Range<T>& r) const { return end_ < r.begin_; }

to RangeSet makes the whole thing work beautifully so I bet it'll now build for
you - comitted in revision 660647
It does. Thanks a lot!

Perhaps the GNU compiler is able to instantiate a whole Range<T> from
the r.begin() argument? However, the Range<T>::Range(const T &t)
constructor is declared as explicit. So, I don't think that should be
the problem

As an outline, does it make sense to pass to std::lower_bound iterators
not compatible with the value argument?

Hah! No it does not. Turns out that one of the requirements on lower_bound is
that "ForwardIterator's value type is the same type as LessThanComparable."
I was under the mistaken impression that it was only required for *i < x to be a
valid expression.

So this whole thing is my goof, thanks for sticking with it.
You're welcome.
Cheers,
Alan.
.

Well, the compiling effort is progressing. I have a fresh libqpidcommon.so.0.1.0 but some other frightening errors arised in the broker side. Once again, I'm not able to figure out what is causing this one:

ource='qpid/broker/SemanticState.cpp' object='qpid/broker/SemanticState.lo' libtool=yes \
DEPDIR=.deps depmode=none /bin/bash ../build-aux/depcomp \
/bin/bash ../libtool --tag=CXX --mode=compile CC -m64 -mt -library=stlport4 -DHAVE_CONFIG_H -I. -Igen -I./gen -I/opt/dslap/contrib/include -c -o qpid/broker/SemanticState.lo qpid/broker/SemanticState.cpp CC -m64 -mt -library=stlport4 -DHAVE_CONFIG_H -I. -Igen -I./gen -I/opt/dslap/contrib/include -c qpid/broker/SemanticState.cpp -KPIC -DPIC -o qpid/broker/.libs/SemanticState.o "./qpid/sys/posix/Mutex.h", line 96: Warning (Anachronism): Formal argument 2 of type extern "C" void(*)() in call to pthread_once(_once*, extern "C" void(*)()) is being passed void(*)(). "./qpid/sys/posix/Mutex.h", line 105: Warning (Anachronism): Formal argument 2 of type extern "C" void(*)() in call to pthread_once(_once*, extern "C" void(*)()) is being passed void(*)(). "./qpid/sys/posix/Thread.h", line 67: Warning (Anachronism): Formal argument 3 of type extern "C" void*(*)(void*) in call to pthread_create(unsigned*, const _pthread_attr*, extern "C" void*(*)(void*), void*) is being passed void*(*)(void*). "./qpid/sys/posix/Thread.h", line 71: Warning (Anachronism): Formal argument 3 of type extern "C" void*(*)(void*) in call to pthread_create(unsigned*, const _pthread_attr*, extern "C" void*(*)(void*), void*) is being passed void*(*)(void*). "/opt/SUNWspro/prod/include/CC/stlport4/stl/_function.h", line 164: Error: Formal argument __r of type qpid::broker::DeliveryRecord& in call to std::mem_fun1_ref_t<void, qpid::broker::DeliveryRecord, qpid::broker::TransactionContext*>::operator()(qpid::broker::DeliveryRecord&, qpid::broker::TransactionContext*) const requires an lvalue. "/opt/SUNWspro/prod/include/CC/stlport4/stl/_algo.h", line 65: Where: While instantiating "std::binder2nd<std::mem_fun1_ref_t<void, qpid::broker::DeliveryRecord, qpid::broker::TransactionContext*>>::operator()(const qpid::broker::DeliveryRecord&) const". "/opt/SUNWspro/prod/include/CC/stlport4/stl/_algo.h", line 65: Where: Instantiated from non-template code.
1 Error(s) and 4 Warning(s) detected.

The compiler is not giving me the offending source line, but just looking at the points of SemanticState.cpp where a DeliveryRecord method with a TransactionContext* argument is called using a bind2nd, has brought me to these two choices: line 418: for_each(start, end, bind2nd(mem_fun_ref(&DeliveryRecord::dequeue), 0)); line 684: for_each(range.start, range.end, bind2nd(mem_fun_ref(&DeliveryRecord::accept), 0));

Commenting out those two lines, leads to this other error:

"/opt/SUNWspro/prod/include/CC/stlport4/stl/_function.h", line 164: Error: Formal argument __r of type qpid::broker::DeliveryRecord& in call to std::mem_fun1_ref_t<void, qpid::broker::DeliveryRecord, bool>::operator()(qpid::broker::DeliveryRecord&, bool) const requires an lvalue. "/opt/SUNWspro/prod/include/CC/stlport4/stl/_algo.h", line 65: Where: While instantiating "std::binder2nd<std::mem_fun1_ref_t<void, qpid::broker::DeliveryRecord, bool>>::operator()(const qpid::broker::DeliveryRecord&) const". "/opt/SUNWspro/prod/include/CC/stlport4/stl/_algo.h", line 65: Where: Instantiated from non-template code.

Probably produced by line 639:

for_each(start, end, bind2nd(mem_fun_ref(&DeliveryRecord::release), setRedelivered));

as it's the only method in DeliveryRecord accepting a bool as argument.

I've read somewhere that std::for_each is not intended to modify the traversed sequence. But I'm not sure if "modifying" means the elements or the sequence itself. I've written this little test:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

class Item {
public:
 Item(int i): m_i(i) {};
 void setIndex(int i) { m_i = i; }
 int getIndex() const { return m_i; }
 void printTo(ostream *os) const { *os << "Item[" << m_i << "] "; }
private:
 int m_i;
};

int main(int argc, char *argv[])
{
 vector<Item> items;
 items.push_back(Item(0));
 items.push_back(Item(1));
 items.push_back(Item(2));
//for_each(items.begin(), items.end(), bind2nd(mem_fun_ref(&Item::setIndex), 0)); for_each(items.begin(), items.end(), bind2nd(mem_fun_ref(&Item::printTo), &cout));
}

Note the first for_each call, commented out. GNU g++ is able to compile and run that program without problem, even without commenting the first for_each call. So, it's able to call a non-const method on the iterated sequence. But that is not true for Sun Studio 12:

-bash-3.00$ CC -o for_each for_each.cc
"/opt/SUNWspro/prod/include/CC/Cstd/./functional", line 327: Error: Formal argument p of type Item& in call to std::mem_fun1_ref_t<void, Item, int>::operator()(Item&, int) const requires an lvalue. "/opt/SUNWspro/prod/include/CC/Cstd/./algorithm.cc", line 64: Where: While instantiating "std::binder2nd<std::mem_fun1_ref_t<void, Item, int>>::operator()(const Item&) const". "/opt/SUNWspro/prod/include/CC/Cstd/./algorithm.cc", line 64: Where: Instantiated from std::for_each<Item*, std::binder2nd<std::mem_fun1_ref_t<void, Item, int>>>(Item*, Item*, std::binder2nd<std::mem_fun1_ref_t<void, Item, int>>).
"for_each.cc", line 24:     Where: Instantiated from non-template code.
1 Error(s) detected.


Perhaps the problem is in the Sun CC STL binder2nd implementation:

template <class _Operation>
class binder2nd
: public unary_function<typename __BINARY_ARG(_Operation,first_argument_type),
                         typename __BINARY_ARG(_Operation,result_type)> {
protected:
 _Operation _M_op;
 typename _Operation::second_argument_type value;
public:
 binder2nd(const _Operation& __x,
           const typename _Operation::second_argument_type& __y)
     : _M_op(__x), value(__y) {}
 typename _Operation::result_type
 operator()(const typename _Operation::first_argument_type& __x) const {
   return _M_op(__x, value);
 }
};

The operator() has a const reference argument, and I think it's triggering the problem. Isn't this restricting binder2nd to only call const methods on the passed object?

Confused greetings.

--
Manuel.












Reply via email to