Boost logo

Boost Users :

From: Chris Fairles (chris.fairles_at_[hidden])
Date: 2007-07-23 14:08:11


I also took a stab at making a boostified version:

#include <iostream>
#include <boost/type_traits/config.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_fundamental.hpp>
#include <boost/type_traits/detail/yes_no_type.hpp>
#include <boost/type_traits/detail/bool_trait_def.hpp>

namespace boost {
namespace detail {

template <class T>
struct has_serialize_mem_fun {
    typedef void (T::*SerializationFun)(int &, unsigned);

    template <SerializationFun>
    struct A {};

    template <class Q>
    static ::boost::type_traits::yes_type
has_serialize_mem_fun_tester(A<&Q::serialize>*);

    template <class Q>
    static ::boost::type_traits::no_type has_serialize_mem_fun_tester(...);

    BOOST_STATIC_CONSTANT(bool, value =
        (sizeof(has_serialize_mem_fun_tester<T>(0)) ==
sizeof(::boost::type_traits::yes_type)));

};
template <typename T, typename IsFundamental = void>
struct is_serializable_impl
{
    BOOST_STATIC_CONSTANT(bool, value = has_serialize_mem_fun<T>::value);
};

template <typename T>
struct is_serializable_impl<T, typename ::boost::enable_if<
::boost::is_fundamental<T> >::type>
{
    BOOST_STATIC_CONSTANT(bool, value = true);
};
}

BOOST_TT_AUX_BOOL_TRAIT_DEF1(is_serializable,T,::boost::detail::is_serializable_impl<T>::value)

}

struct A {
    template <class Stream>
    void serialize(Stream & strm, unsigned version) {}
};

struct B {};

struct C { void serialize() {} };

int main()
{
    using namespace std;
    cout
        << boolalpha
        << boost::is_serializable<A>::value << '\n' // true
        << boost::is_serializable<int>::value << '\n' // true
        << boost::is_serializable<float>::value << '\n' // true
        << boost::is_serializable<double>::value << '\n' // true
        << boost::is_serializable<char>::value << '\n' // true
        << boost::is_serializable<B>::value << '\n' // false
        << boost::is_serializable<C>::value << '\n' // false
        << boost::is_serializable<string>::value << endl; //false but
should be true
}

Needs specializations for standard containers as well but this suits
my needs currently. Thoughts?

On 7/23/07, Chris Fairles <chris.fairles_at_[hidden]> wrote:
> Thanks!
>
> I kept trying things with void(A::*serialize)(blah, const unsigned
> int) in my test function. Like:
>
> template<typename T>
> class IsSerializableClassT {
> private:
> typedef char One;
> typedef struct { char a[2]; } Two;
> template<typename C> static Two test(...);
> template<typename C> static One test(void(C::*)(int,int));
> public:
> enum { Yes = sizeof(IsClassT<T>::template test<T>(0)) == 1 };
> enum { No = !Yes };
> };
>
> But, when resolving test(...) vs. the member func pointer, it picks
> the mem func pointer for any class even if it doesn't have a func with
> that specific signature.
>
> That local tempalte trick you use solves the issue. A local template
> with a non-type member-function parameter (which i only recently
> learned was even possible!), void(T::*)(int&,int)....
>
> So the substitution fails if the supplied fuction doesn't match the
> signature. So whats the technical reason why the substitution doesn't
> fail based on mem func ptr signature in a function parameter? I guess
> function arguments aren't bound until runtime so it never really looks
> in the class for the function at compile time?
>
> Chris
>
> On 7/23/07, Robert Ramey <ramey_at_[hidden]> wrote:
> >
> >
> > Very clever, I would expect some variation of this to end up somewhere in
> > the library itself some day.
> >
> > Robert Ramey
> >
> > "Roman Perepelitsa" <roman.perepelitsa_at_[hidden]> wrote in message
> > news:OFC1A16EC6.69CEAA30-ONC3257321.002322F2-C3257321.0023748C_at_db.com...
> >
> > > Chris Fairles" <chris.fairles_at_[hidden]> on Fri, 20 Jul 2007 18:03:18
> > -0400
> > > How can you determine (compile-time) that a class has a serialize
> > function?
> > >
> > > struct foo {
> > > template <typename Archive>
> > > void serialize (Archive &, const unsigned int);
> > > };
> > >
> > > "&foo::serialize" isn't a type and I can't figure out a way to make it
> > > a type (besides a typedef in the class) and also a constant
> > > expression.
> > >
> > > Tried to play around with this as well but theres no substitution
> > > failure here and static functions can't be constant expressions
> > > (commonnnn c++0x!!)
> > >
> > > struct serialize {
> > > template <typename T>
> > > static void value(T const&) {
> > void(T::*f)(archive::xml_oarchive &,
> > > const unsigned int) = &T::template
> > serialize<archive::xml_oarchive>;
> > > (void)f; }
> > > };
> > >
> > > Basically, in the code below I want to see "GoodGood" printed out and
> > > the only thing I can change is Q.
> > >
> > > struct A{
> > > void f(int,int){}
> > > };
> > > struct B{};
> > >
> > > template <class T,class F=void>
> > > struct Q{enum{value=false};};
> > >
> > > template<class T> struct
> > Q<T,void(T::serialize)(int,int)>{enum{value=true};};
> > >
> > > int main(){
> > > if(Q<A>::value) { cout << "Good";}
> > > if(!Q<B>::value){ cout << "Good";}
> > > }
> > >
> > > Help/hints/remotely possible?
> >
> > You can try something like this.
> >
> > #include <iostream>
> > #include <iomanip>
> >
> > typedef char yes_type;
> >
> > struct no_type
> > {
> > char padding[8];
> > };
> >
> > template <class T>
> > struct HasSerializeMember
> > {
> > typedef void (T::*SerializationFun)(int &, unsigned);
> >
> > template <SerializationFun>
> > struct A {};
> >
> > template <class Q>
> > static yes_type Test(A<&Q::serialize>*);
> >
> > template <class Q>
> > static no_type Test(...);
> >
> > static const bool value =
> > sizeof(Test<T>(0)) == sizeof(yes_type);
> > };
> >
> > struct A
> > {
> > template <class Stream>
> > void serialize(Stream & strm, unsigned version) {}
> > };
> >
> > struct B
> > {
> > };
> >
> > struct C
> > {
> > void serialize() {}
> > };
> >
> > int main()
> > {
> > using namespace std;
> > cout
> > << boolalpha
> > << HasSerializeMember<A>::value << '\n' // true
> > << HasSerializeMember<B>::value << '\n' // false
> > << HasSerializeMember<C>::value << endl; // false
> > }
> >
> > Regards,
> > Roman Perepelitsa
> >
> > Deutsche Bank Moscow
> > +7 (495) 660-74-08
> >
> > ---
> >
> > This e-mail may contain confidential and/or privileged information. If you
> > are not the intended recipient (or have received this e-mail in error)
> > please notify the sender immediately and delete this e-mail. Any
> > unauthorized copying, disclosure or distribution of the material in this
> > e-mail is strictly forbidden.
> >
> > Please refer to
> > http://www.db.com/en/content/eu_disclosures.htm for
> > additional EU corporate and regulatory disclosures.
> >
> >
> > ________________________________
> >
> >
> > _______________________________________________
> > Boost-users mailing list
> > Boost-users_at_[hidden]
> > http://lists.boost.org/mailman/listinfo.cgi/boost-users
> >
> >
> > _______________________________________________
> > Boost-users mailing list
> > Boost-users_at_[hidden]
> > http://lists.boost.org/mailman/listinfo.cgi/boost-users
> >
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net