Re: [sigc] libsigc++ 1.9.13 fails on Solaris 9 sparc



Am 2004.03.15 20:03 schrieb(en) Murray Cumming:
On Mon, 2004-03-15 at 12:23, Damien Carbery wrote:
> Murray Cumming wrote:
> > On Sat, 2004-03-06 at 00:10, Martin Schulze wrote:
> >
> >>Am 2004.03.04 17:22 schrieb(en) Damien Carbery:
> >>
> >>>Apologies for not doing this build earlier in the week. Busy.
> >>>I updated tests/test_mem_fun.cc and tests/test_ptr_fun.cc and
rebuilt
> >>>(make clean; make).
> >>>Log is attached.
> >>
> >>Please try again with the version of file sigc++/adaptors/macros/
> >>adaptor_trait.h.m4 that is attached to this email. The problem is
> >>the syntax for explicit method template specializations. gcc
expects:
> >
> >
> > Martin, is all this stuff in cvs so far? I now have access to a
SUN
> > Forte compiler, though it might not be the same as Damien's:
> >
> > bash-2.03$ CC -V
> > CC: Sun WorkShop 6 update 2 C++ 5.3 Patch 111685-11 2002/10/31
> >
> > Damien, what does CC -V give you?
> >
>
> CC: Sun C++ 5.5 Patch 113817-03 2003/10/14
> It is from the Sun ONE Studio 8 Compiler Collection.
> http://wwws.sun.com/software/products/studio/index.html

Hmm, maybe 5.5 is much more capable than 5.3 - but I'd be happy if at
least one of them can build libsigc++ 2. I'm not sure at what point
you
are, and exactly what sources you are both investigating - could
someone
explain?

First, sorry for my absence. I was at a conference in Kiel last week.

Great that we have access to two SUN boxes now :)

I'm attaching the "corrected" test cases and adaptor_trait.h.m4 I already sent to Demian. I didn't want to check in this stuff until it is clear that the changes really help - they are quite experimental and Demian couldn't work with CVS anyway until now because of his outdated autoconf version (has this changed, by the way?).

Demain has been working with a patched libsigc++-1.9.14. All patches
but the most recent ones affecting the test cases and adaptor_trait.h. m4 (-> attachement) are checked in cvs.

Regards,

 Martin
dnl Copyright 2002, The libsigc++ Development Team 
dnl 
dnl This library is free software; you can redistribute it and/or 
dnl modify it under the terms of the GNU Lesser General Public 
dnl License as published by the Free Software Foundation; either 
dnl version 2.1 of the License, or (at your option) any later version. 
dnl 
dnl This library is distributed in the hope that it will be useful, 
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of 
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
dnl Lesser General Public License for more details. 
dnl 
dnl You should have received a copy of the GNU Lesser General Public 
dnl License along with this library; if not, write to the Free Software 
dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
dnl
divert(-1)
include(template.macros.m4)

dnl
dnl The idea here is simple.  To prevent the need to 
dnl specializing every adaptor for every type of functor
dnl and worse non-functors like function pointers, we
dnl will make an adaptor trait which can take ordinary
dnl functors and make them adaptor functors for which 
dnl we will of course be able to avoid excess copies. 
dnl (in theory)
dnl
dnl this all depends on partial specialization to allow
dnl us to do
dnl   functor_.template operator() <types> (args);
dnl

dnl I don't understand much of the above. However, I can
dnl see that adaptors are implemented like they are because
dnl there is no way to extract the return type and the argument
dnl types from a functor type. Therefore, operator() is templated.
dnl It's instatiated in slot_call#<>::operator() where the
dnl argument types are known. The return type is finally determined
dnl via the callof<> template - a tricky way to detect the return
dnl type of a functor when the argument types are known. Martin.

])
define([ADAPTOR_DO],[dnl
ifelse($1,0,[dnl
dnl  typename internal::callof_safe0<T_functor>::result_type // doesn't compile if T_functor has an overloaded operator()!
dnl  typename functor_trait<T_functor>::result_type
dnl  operator()() const
dnl    { return functor_(); }
],[dnl
  /** Invokes the wrapped functor passing on the arguments.dnl
FOR(1, $1,[
   * @param _A_arg%1 Argument to be passed on to the functor.])
   * @return The return value of the functor invocation.
   */
  template <LOOP([class T_arg%1], $1)>
  typename deduce_result_type<LOOP(T_arg%1, $1)>::type
  operator()(LOOP(T_arg%1 _A_arg%1, $1)) const
    { return functor_(LOOP(_A_arg%1, $1)); }

])dnl
])

divert(0)dnl
__FIREWALL__
#include <sigc++/visit_each.h>
#include <sigc++/functors/functor_trait.h>
#include <sigc++/functors/ptr_fun.h>
#include <sigc++/functors/mem_fun.h>
#include <sigc++/adaptors/deduce_result_type.h>

namespace sigc {

#ifndef GCC
#define LIBSIGC_TEMPLATE_PREFIX
#else
#define LIBSIGC_TEMPLATE_PREFIX template
#endif

template <class T_functor> struct adapts;

/** @defgroup adaptors Adaptors
 * Adaptors are functors that alter the signature of a functor's
 * operator()().
 *
 * The adaptor types libsigc++ provides
 * are created with bind(), bind_return(), hide(), hide_return(),
 * retype_return(), retype(), compose(), exception_catch() and group().
 *
 * You can easily derive your own adaptor type from sigc::adapts.
 */

/** Converts an arbitrary functor into an adaptor type.
 * All adaptor tyes in libsigc++ are unnumbered and have
 * a <tt>template operator()</tt> member of every argument count
 * they support. These functions in turn invoke a stored adaptor's
 * <tt>template operator()</tt> processing the arguments and return
 * value in a characteristic manner. Explicit function template
 * instantiation is used to pass type hints thus saving copy costs.
 *
 * adaptor_functor is a glue between adaptors and arbitrary functors
 * that just passes on the arguments. You won't use this type directly.
 *
 * The template argument @e T_functor determines the type of stored
 * functor.
 *
 * @ingroup adaptors
 */
template <class T_functor>
struct adaptor_functor : public adaptor_base
{
  template <LOOP(class T_arg%1=void, CALL_SIZE)>
  struct deduce_result_type
    { typedef typename sigc::deduce_result_type<LIST(T_functor, LOOP(T_arg%1,CALL_SIZE))>::type type; };
  typedef typename functor_trait<T_functor>::result_type result_type;

  /** Invokes the wrapped functor passing on the arguments.
   * @return The return value of the functor invocation.
   */
  result_type
  operator()() const;

FOR(0,CALL_SIZE,[[ADAPTOR_DO(%1)]])dnl
  /// Constructs an invalid functor.
  adaptor_functor()
    {}

  /** Constructs an adaptor_functor object that wraps the passed functor.
   * @param _A_functor Functor to invoke from operator()().
   */
  explicit adaptor_functor(const T_functor& _A_functor)
    : functor_(_A_functor)
    {}

  /** Constructs an adaptor_functor object that wraps the passed (member)
   * function pointer.
   * @param _A_type Pointer to function or class method to invoke from operator()().
   */
  template <class T_type>
  explicit adaptor_functor(const T_type& _A_type)
    : functor_(_A_type)
    {}

  /// Functor that is invoked from operator()().
  mutable T_functor functor_;
};

template <class T_functor>
typename adaptor_functor<T_functor>::result_type
adaptor_functor<T_functor>::operator()() const
  { return functor_(); }


/** Performs a functor on each of the targets of a functor.
 * The function overload for sigc::adaptor_functor performs a functor
 * on the functor stored in the sigc::adaptor_functor object.
 *
 * @ingroup adaptors
 */
template <class T_action, class T_functor>
void visit_each(const T_action& _A_action,
                const adaptor_functor<T_functor>& _A_target)
{
  visit_each(_A_action, _A_target.functor_);
}


/** Trait that specifies what is the adaptor version of a functor type.
 * Template specializations for sigc::adaptor_base derived functors,
 * for function pointers and for class methods are provided.
 *
 * The template argument @e T_functor is the functor type to convert.
 * @e I_isadaptor indicates whether @e T_functor inherits from sigc::adaptor_base.
 *
 * @ingroup adaptors
 */
template <class T_functor, bool I_isadaptor = is_base_and_derived<adaptor_base, T_functor>::value> struct adaptor_trait;

/** Trait that specifies what is the adaptor version of a functor type.
 * This template specialization is used for types that inherit from adaptor_base.
 * adaptor_type is equal to @p T_functor in this case.
 */
template <class T_functor> 
struct adaptor_trait<T_functor, true>
{
  typedef typename T_functor::result_type result_type;
  typedef T_functor functor_type;
  typedef T_functor adaptor_type;
};

/** Trait that specifies what is the adaptor version of a functor type.
 * This template specialization is used for arbitrary functors,
 * for function pointers and for class methods are provided.
 * The latter are converted into @p pointer_functor or @p mem_functor types.
 * adaptor_type is equal to @p adaptor_functor<functor_type>.
 */
template <class T_functor>
struct adaptor_trait<T_functor, false>
{
  typedef typename functor_trait<T_functor>::result_type result_type;
  typedef typename functor_trait<T_functor>::functor_type functor_type;
  typedef adaptor_functor<functor_type> adaptor_type;
};


/** Base type for adaptors.
 * adapts wraps adaptors, functors, function pointers and class methods.
 * It contains a single member functor which is always a sigc::adaptor_base.
 * The typedef adaptor_type defines the exact type that is used
 * to store the adaptor, functor, function pointer or class method passed
 * into the constructor. It differs from @e T_functor unless @e T_functor
 * inherits from sigc::adaptor_base.
 *
 * @par Example of a simple adaptor:
 *   @code
 *   template <T_functor>
 *   struct my_adpator : public sigc::adapts<T_functor>
 *   {
 *     template <class T_arg1=void, class T_arg2=void>
 *     struct deduce_result_type
 *     { typedef typename sigc::deduce_result_type<T_functor, T_arg1, T_arg2>::type type; };
 *     typedef typename sigc::functor_trait<T_functor>::result_type result_type;
 *
 *     result_type
 *     operator()() const;
 *
 *     template <class T_arg1>
 *     typename deduce_result_type<T_arg1>::type
 *     operator()(T_arg1 _A_arg1) const;
 *
 *     template <class T_arg1, class T_arg2>
 *     typename deduce_result_type<T_arg1, T_arg2>::type
 *     operator()(T_arg1 _A_arg1, class T_arg2) const;
 *
 *     explicit adaptor_functor(const T_functor& _A_functor) // Constructs a my_functor object that wraps the passed functor.
 *       : sigc::adapts<T_functor>(_A_functor) {}
 *
 *     mutable T_functor functor_; // Functor that is invoked from operator()().
 *   };
 *   @endcode
 *
 * @ingroup adaptors
 */
template <class T_functor>
struct adapts : public adaptor_base
{
  typedef typename adaptor_trait<T_functor>::result_type  result_type;
  typedef typename adaptor_trait<T_functor>::adaptor_type adaptor_type;

  /** Constructs an adaptor that wraps the passed functor.
   * @param _A_functor Functor to invoke from operator()().
   */
  explicit adapts(const T_functor& _A_functor)
    : functor_(_A_functor)
    {}

  /// Adaptor that is invoked from operator()().
  mutable adaptor_type functor_;
};

} /* namespace sigc */
// -*- c++ -*-
/* Copyright 2002, The libsigc++ Development Team
 *  Assigned to public domain.  Use as you wish without restriction.
 */

#include <sigc++/functors/mem_fun.h>
#include <iostream>

struct test
{
void foo(short i1)
  {std::cout << "const test::foo(short "<< i1<< ')' <<std::endl; }
void foo_const(int i1) const
  {std::cout << "const test::foo(int "<< i1<< ')' <<std::endl; }
void foo_volatile(float i1) volatile
  {std::cout << "const test::foo(float "<< i1<< ')' <<std::endl; }
void foo_const_volatile(double i1) const volatile
  {std::cout << "const test::foo(double "<< i1<< ')' <<std::endl; }

void foo_overloaded(char i1)
  {std::cout << "const test::foo(char "<< (int)i1<< ')' <<std::endl; }
/* TODO: put something like #ifndef FORTE ... #endif around:
void foo_overloaded(short i1)
  {std::cout << "const test::foo(char "<< (int)i1<< ')' <<std::endl; } */
double foo_overloaded(int i1,int i2)
  {std::cout << "test::foo("<<i1<<','<<i2<< ')' <<std::endl; return 1.0;}
};

int main()
{
   { /* test non-const */
     test t;
     sigc::mem_fun(&test::foo)(t,1);  // on reference
     sigc::mem_fun(&test::foo)(&t,1); // on pointer
   }
   { /* test const */
     test t;
     sigc::mem_fun(&test::foo_const)(t,2);
     sigc::mem_fun(&test::foo_const)(&t,2);
   }
   { /* test const with const object */
     const test t=test();
     sigc::mem_fun(&test::foo_const)(t,3);
     sigc::mem_fun(&test::foo_const)(&t,3);
   }
   { /* test non-const volatile */
     test t;
     sigc::mem_fun(&test::foo_volatile)(t,4);  // on reference
     sigc::mem_fun(&test::foo_volatile)(&t,4); // on pointer
   }
   { /* test const volatile */
     test t;
     sigc::mem_fun(&test::foo_const_volatile)(t,5);  // on reference
     sigc::mem_fun(&test::foo_const_volatile)(&t,5); // on pointer
   }
   { /* test const volatile with const object */
     const test t=test();
     sigc::mem_fun(&test::foo_const_volatile)(t,6);  // on reference
     sigc::mem_fun(&test::foo_const_volatile)(&t,6); // on pointer
   }
   { /* test overloaded */
     test t;
/* TODO: put something like #ifndef FORTE ... #else ... #endif around:
     sigc::mem_fun1<char>(&test::foo_overloaded)(&t,7);
     sigc::mem_fun1<short>(&test::foo_overloaded)(&t,7); and: */
     sigc::mem_fun1(&test::foo_overloaded)(&t,7);
     sigc::mem_fun2(&test::foo_overloaded)(&t,7,8);
   }
   { /* test bound */
     test t;
     sigc::mem_fun(t,&test::foo)(9);
     sigc::mem_fun(&t,&test::foo)(9);
     sigc::mem_fun(t,&test::foo_const)(9);
     sigc::mem_fun(&t,&test::foo_const)(9);
     sigc::mem_fun(t,&test::foo_volatile)(9);
     sigc::mem_fun(&t,&test::foo_volatile)(9);
     sigc::mem_fun2(t,&test::foo_overloaded)(9,10);
     sigc::mem_fun2(&t,&test::foo_overloaded)(9,10);
   }
}
// -*- c++ -*-
/* Copyright 2002, The libsigc++ Development Team
 *  Assigned to public domain.  Use as you wish without restriction.
 */

#include <iostream>
#include <sigc++/functors/ptr_fun.h>

int foo()
  {std::cout << "foo()" << std::endl; return 1;}
void foo(int i1)
  {std::cout << "foo(int "<<i1<<")" << std::endl;}

/* TODO: put something like #ifndef FORTE ... #endif around:
void bar(char i1)
  {std::cout << "foo(char "<<(int)i1<<")" << std::endl;} */
void bar(float i1)
  {std::cout << "foo(float "<<i1<<")" << std::endl;}
double bar(int i1,int i2)
  {std::cout << "foo(int "<<i1<<", int "<<i2<< ")" <<std::endl; return 1.0f;}

struct test {
  static void foo() {std::cout << "test::foo()" <<std::endl;}
};

int main()
{
  sigc::ptr_fun0(&foo)();
  sigc::ptr_fun1(&foo)(1);
/* TODO: put something like #ifndef FORTE ... #else ... #endif around:
  sigc::ptr_fun1<char>(&bar)(2);
  sigc::ptr_fun1<float>(&bar)(2.0f); and: */
  sigc::ptr_fun1(&bar)(2.0f);
  sigc::ptr_fun2(&bar)(3,5);
  sigc::ptr_fun(&test::foo)();
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]