From: g0dil Date: Wed, 9 Apr 2008 18:56:16 +0000 (+0000) Subject: Utils: Add unit-test and documentation for type_traits.hh X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=869df8df564cd4f4934d4cd1c1b290c2aeabbd92;p=senf.git Utils: Add unit-test and documentation for type_traits.hh Utils: Add some more type_traits Console: Implement parsed command attributor git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@797 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Console/Node.cti b/Console/Node.cti index ef80237..69baef1 100644 --- a/Console/Node.cti +++ b/Console/Node.cti @@ -34,7 +34,7 @@ // senf::console::NodeCreateTraits::Creator template -prefix_ typename senf::console::NodeCreateTraits::NodeType & +prefix_ typename senf::console::NodeCreateTraits::result_type senf::console::NodeCreateTraits::Creator::create(DirectoryNode & node, std::string const & name, Object const & ob) @@ -56,7 +56,7 @@ prefix_ NodeType & senf::console::DirectoryNode::add(std::string const & name, } template -prefix_ typename senf::console::NodeCreateTraits::NodeType & +prefix_ typename senf::console::NodeCreateTraits::result_type senf::console::DirectoryNode::add(std::string const & name, Object const & ob) { return NodeCreateTraits::Creator::create(*this, name, ob); diff --git a/Console/Node.hh b/Console/Node.hh index 29c5511..9bf37ec 100644 --- a/Console/Node.hh +++ b/Console/Node.hh @@ -205,6 +205,7 @@ #include "../Utils/Exception.hh" #include "../Utils/mpl.hh" #include "../Utils/Logger/SenfLog.hh" +#include "../Utils/type_traits.hh" #include "Parse.hh" //#include "Node.mpp" @@ -306,14 +307,16 @@ namespace console { * static_cast(0), * static_cast(0), * static_cast(0), - 0) ) result_type; + 0) ) base_type; + typedef typename senf::remove_cvref::type value_type; - typedef typename boost::remove_reference::type NodeType; + typedef typename value_type::node_type NodeType; + typedef typename value_type::return_type result_type; /// Internal struct Creator { - static NodeType & create(DirectoryNode & node, std::string const & name, - Object const & ob); + static result_type create(DirectoryNode & node, std::string const & name, + Object const & ob); }; }; @@ -353,6 +356,9 @@ namespace console { typedef boost::iterator_range ChildrenRange; typedef ChildMap::const_iterator child_iterator; + typedef DirectoryNode node_type; + typedef DirectoryNode & return_type; + /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members ///\{ @@ -376,8 +382,8 @@ namespace console { \a name is empty, it is set to 'unnamed'. */ template - typename NodeCreateTraits::NodeType & add (std::string const & name, - Object const & ob); + typename NodeCreateTraits::result_type add (std::string const & name, + Object const & ob); ///< Generic child node factory /**< This member is used to create a new child node of the current directory. The type of node created depends on @@ -584,6 +590,9 @@ namespace console { typedef boost::function Function; + typedef SimpleCommandNode node_type; + typedef SimpleCommandNode & return_type; + /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members ///\{ diff --git a/Console/OverloadedCommand.hh b/Console/OverloadedCommand.hh index 48b1097..e7b5692 100644 --- a/Console/OverloadedCommand.hh +++ b/Console/OverloadedCommand.hh @@ -138,6 +138,9 @@ namespace console { typedef boost::shared_ptr cptr; typedef boost::weak_ptr weak_ptr; + typedef OverloadedCommandNode node_type; + typedef OverloadedCommandNode & return_type; + /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members ///@{ diff --git a/Console/ParsedCommand.cci b/Console/ParsedCommand.cci index 94bbf32..0317002 100644 --- a/Console/ParsedCommand.cci +++ b/Console/ParsedCommand.cci @@ -49,6 +49,58 @@ prefix_ void senf::console::ParsedCommandOverloadBase::doc(std::string const & d doc_ = d; } +/////////////////////////////////////////////////////////////////////////// +// senf::console::ParsedCommandAttributorBase + +prefix_ senf::console::OverloadedCommandNode & +senf::console::ParsedCommandAttributorBase::node() + const +{ + return overload_.node(); +} + +prefix_ senf::console::ParsedCommandAttributorBase::operator OverloadedCommandNode &() + const +{ + return node(); +} + +prefix_ senf::console::ParsedCommandAttributorBase:: +ParsedCommandAttributorBase(ParsedCommandOverloadBase & overload, unsigned index) + : overload_ (overload), index_ (index) +{} + +prefix_ void senf::console::ParsedCommandAttributorBase::argName(std::string const & name) + const +{ + overload().arg(index_).name = name; +} + +prefix_ void senf::console::ParsedCommandAttributorBase::argDoc(std::string const & doc) + const +{ + overload().arg(index_).doc = doc; +} + +prefix_ senf::console::ParsedCommandOverloadBase & +senf::console::ParsedCommandAttributorBase::overload() + const +{ + return overload_; +} + +prefix_ void senf::console::ParsedCommandAttributorBase::overloadDoc(std::string const & doc) + const +{ + overload().doc(doc); +} + +prefix_ void senf::console::ParsedCommandAttributorBase::nodeDoc(std::string const & doc) + const +{ + node().doc(doc); +} + ///////////////////////////////cci.e/////////////////////////////////////// #undef prefix_ diff --git a/Console/ParsedCommand.cti b/Console/ParsedCommand.cti index 60b7fde..6809191 100644 --- a/Console/ParsedCommand.cti +++ b/Console/ParsedCommand.cti @@ -58,6 +58,122 @@ prefix_ void senf::console::ParsedCommandOverloadBase::addParameter() #include BOOST_PP_ITERATE() /////////////////////////////////////////////////////////////////////////// +// senf::console::ParsedCommandAttributorBase + +template +prefix_ void senf::console::ParsedCommandAttributorBase::defaultValue(Type const & value) + const +{ + overload().arg(index_).defaultValue = value; + overload().arg(index_).hasDefault = true; +} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::ParsedCommandAttributor + +template +prefix_ Overload & senf::console::ParsedCommandAttributor::overload() + const +{ + return static_cast(ParsedCommandAttributorBase::overload()); +} + +template +prefix_ +senf::console::ParsedCommandAttributor::ParsedCommandAttributor(Overload & overload, + unsigned index) + : ParsedCommandAttributorBase (overload, index) +{} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::ParsedAttributeAttributorBase + +template +prefix_ Self +senf::console::ParsedAttributeAttributorBase::doc(std::string const & doc) + const +{ + this->ParsedCommandAttributorBase::nodeDoc(doc); + return static_cast(*this); +} + +template +prefix_ Self senf::console::ParsedAttributeAttributorBase:: +overloadDoc(std::string const & doc) + const +{ + this->ParsedCommandAttributorBase::overloadDoc(doc); + return static_cast(*this); +} + +template +prefix_ +senf::console::ParsedAttributeAttributorBase:: +ParsedAttributeAttributorBase(Overload & overload, unsigned index) + : ParsedCommandAttributor (overload, index) +{} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::ParsedAttributeAttributor + +template +prefix_ senf::console::ParsedAttributeAttributor +senf::console::ParsedAttributeAttributor::arg(std::string const & name, + std::string const & doc) + const +{ + this->argName(name); + this->argDoc(doc); + return next(); +} + +template +prefix_ senf::console::ParsedAttributeAttributor +senf::console::ParsedAttributeAttributor::arg(std::string const & name, + std::string const & doc, + value_type const & value) + const +{ + this->argName(name); + this->argDoc(doc); + defaultValue(value); + return next(); +} + +template +prefix_ +senf::console::ParsedAttributeAttributor:: +ParsedAttributeAttributor(Overload & overload) + : ParsedAttributeAttributorBase (overload, index) +{} + +template +prefix_ senf::console::ParsedAttributeAttributor +senf::console::ParsedAttributeAttributor::next() + const +{ + return ParsedAttributeAttributor(this->overload()); +} + +template +prefix_ void senf::console::ParsedAttributeAttributor:: +defaultValue(value_type const & value) + const +{ + ParsedCommandAttributorBase::defaultValue(value); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::ParsedAttributeAttributor + +template +prefix_ +senf::console::ParsedAttributeAttributor:: +ParsedAttributeAttributor(Overload & overload) + : ParsedAttributeAttributorBase (overload, index) +{} + +/////////////////////////////////////////////////////////////////////////// // namespace members namespace { @@ -98,8 +214,9 @@ namespace { } template -prefix_ senf::console::ParsedCommandOverload< - typename senf::console::detail::ParsedCommandTraits::traits> & +prefix_ senf::console::ParsedAttributeAttributor< + senf::console::ParsedCommandOverload< + typename senf::console::detail::ParsedCommandTraits::traits> > senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int) { @@ -108,15 +225,19 @@ senf::console::senf_console_add_node(DirectoryNode & node, std::string const & n ? dynamic_cast(node(name)) : node.add(name, OverloadedCommandNode::create()) ); - typedef senf::console::detail::ParsedCommandTraits CmdTraits; + typedef detail::ParsedCommandTraits CmdTraits; + typedef ParsedCommandOverload Overload; + typedef ParsedAttributeAttributor Attributor; - return cmdNode.add( CreateParsedCommandOverload< - typename CmdTraits::traits, ! CmdTraits::has_ostream_arg>::create(fn) ); + return Attributor( + cmdNode.add( CreateParsedCommandOverload< + typename CmdTraits::traits, ! CmdTraits::has_ostream_arg>::create(fn) ) ); } template -prefix_ senf::console::ParsedCommandOverload< - typename senf::console::detail::ParsedCommandTraits::traits> & +prefix_ senf::console::ParsedAttributeAttributor< + senf::console::ParsedCommandOverload< + typename senf::console::detail::ParsedCommandTraits::traits> > senf::console:: senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name, Function fn, int, @@ -127,11 +248,14 @@ senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & n ? dynamic_cast(node(name)) : node.add(name, OverloadedCommandNode::create()) ); - typedef senf::console::detail::ParsedCommandTraits CmdTraits; + typedef detail::ParsedCommandTraits CmdTraits; + typedef ParsedCommandOverload Overload; + typedef ParsedAttributeAttributor Attributor; - return cmdNode.add( CreateParsedCommandOverload< - typename CmdTraits::traits, ! CmdTraits::has_ostream_arg>::create( - senf::membind(fn,&owner)) ); + return Attributor( + cmdNode.add( CreateParsedCommandOverload< + typename CmdTraits::traits, ! CmdTraits::has_ostream_arg>::create( + senf::membind(fn,&owner)) ) ); } ///////////////////////////////cti.e/////////////////////////////////////// diff --git a/Console/ParsedCommand.hh b/Console/ParsedCommand.hh index 70f4203..020fe6f 100644 --- a/Console/ParsedCommand.hh +++ b/Console/ParsedCommand.hh @@ -80,14 +80,136 @@ namespace console { 1)) # include BOOST_PP_ITERATE() + class ParsedCommandAttributorBase + { + public: + OverloadedCommandNode & node() const; + operator OverloadedCommandNode & () const; + + protected: + ParsedCommandAttributorBase(ParsedCommandOverloadBase & overload, unsigned index); + + void argName(std::string const & name) const; + void argDoc(std::string const & doc) const; + template void defaultValue(Type const & value) const; + + ParsedCommandOverloadBase & overload() const; + void overloadDoc(std::string const & doc) const; + + void nodeDoc(std::string const & doc) const; + + private: + ParsedCommandOverloadBase & overload_; + unsigned index_; + }; + + template + class ParsedCommandAttributor + : public ParsedCommandAttributorBase + { + public: + Overload & overload() const; + + protected: + ParsedCommandAttributor(Overload & overload, unsigned index); + + private: + }; + + template + class ParsedAttributeAttributorBase + : public ParsedCommandAttributor + { + public: + Self doc(std::string const & doc) const; + Self overloadDoc(std::string const & doc) const; + + protected: + ParsedAttributeAttributorBase(Overload & overload, unsigned index); + + private: + }; + + template + class ParsedAttributeAttributor + : public ParsedAttributeAttributorBase< Overload, + ParsedAttributeAttributor > + { + public: + typedef typename senf::function_traits_arg_type< + typename Overload::traits, int(index) >::type arg_type; + typedef typename senf::remove_cvref< arg_type >::type value_type; + + typedef OverloadedCommandNode node_type; + typedef ParsedAttributeAttributor return_type; + + ParsedAttributeAttributor arg(std::string const & name = "", + std::string const & doc = "") const; + ParsedAttributeAttributor arg(std::string const & name, + std::string const & doc, + value_type const & value) const; + + private: + explicit ParsedAttributeAttributor(Overload & overload); + + ParsedAttributeAttributor next() const; + + void defaultValue(value_type const & value) const; + + template + friend class ParsedAttributeAttributor; + + template + friend ParsedAttributeAttributor< + ParsedCommandOverload::traits> > + senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int); + + template + friend ParsedAttributeAttributor< + ParsedCommandOverload::traits> > + senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name, + Function fn, int, + typename boost::enable_if_c::is_member>::type * = 0); + }; + + template + class ParsedAttributeAttributor + : public ParsedAttributeAttributorBase< Overload, + ParsedAttributeAttributor > + { + public: + typedef OverloadedCommandNode node_type; + typedef ParsedAttributeAttributor return_type; + + private: + explicit ParsedAttributeAttributor(Overload & overload); + + template + friend class ParsedAttributeAttributor; + + template + friend ParsedAttributeAttributor< + ParsedCommandOverload::traits> > + senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int); + + template + friend ParsedAttributeAttributor< + ParsedCommandOverload::traits> > + senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name, + Function fn, int, + typename boost::enable_if_c::is_member>::type * = 0); + }; + #ifndef DOXYGEN template - ParsedCommandOverload::traits> & + ParsedAttributeAttributor< + ParsedCommandOverload::traits> > senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int); template - ParsedCommandOverload::traits> & + ParsedAttributeAttributor< + ParsedCommandOverload::traits> > senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name, Function fn, int, typename boost::enable_if_c::is_member>::type * = 0); @@ -99,6 +221,7 @@ namespace console { #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedCommandOverload, (class,unsigned)) +BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedAttributeAttributor, (class, unsigned, bool)) BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function_traits, 1) ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Console/ParsedCommand.mpp b/Console/ParsedCommand.mpp index 2aadffc..b2830ea 100644 --- a/Console/ParsedCommand.mpp +++ b/Console/ParsedCommand.mpp @@ -70,9 +70,8 @@ public: mpp_TrailingArgTypes())> Function; # define mpp_l(z,n,d) \ - typedef typename boost::remove_const< \ - typename boost::remove_reference< typename traits::mpp_ArgTypeN(n) >::type >::type \ - mpp_ArgTypeN(n); + typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type \ + mpp_ArgTypeN(n); BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ ) # undef mpp_l diff --git a/Console/ParsedCommand.test.cc b/Console/ParsedCommand.test.cc index 5b90f2c..b7c78d6 100644 --- a/Console/ParsedCommand.test.cc +++ b/Console/ParsedCommand.test.cc @@ -118,28 +118,30 @@ BOOST_AUTO_UNIT_TEST(parsedCommand) { std::stringstream ss; - senf::console::ParsedCommandOverloadBase & c1 (dir.add("cb", &cb1)); - c1.doc( - "Lo nam balnearius Opprimo Pennatus, no decentia sui, dicto esse se pulchritudo,\n" - "pupa Sive res indifferenter. Captivo pa."); - c1.arg(0).doc = "Bar didelfrump di desgorb. Nu widsoflar brimeldrgf."; - c1.arg(1).name = "checkup"; - c1.arg(1).doc = "Florgel, dargel and durgel"; - c1.arg(1).defaultValue = 2.1; - c1.arg(1).hasDefault = true; - senf::console::ParsedCommandOverloadBase & c5 (dir.add("cb", &cb5)); - c5.doc( - "Uus Primordia fundo falsidicus corium, diurnitas humo pro leto. Sui Ueraciter\n" - "hio eruca lenis qua Agalmate ut fors penitentia. Iugum obdormio anxio nuncupo\n" - "iam, in vos nam Custodi."); + senf::console::OverloadedCommandNode & cbNode ( dir.add("cb", &cb1) + .doc( + "Ops fortunate, ops me ut orgia vociferatio contumax per, rudo re loco emitto\n" + "intolerabiliter ita iugo. Subcribo gravo. Devenio luna fonticulus Castanea\n" + "horum fascino Os interpretor non ipse conjuratio hora, qui filius denuntio ait\n" + "sono te odium Anhelo. Dum Cedo audax celox alius una Agnosco hic, ibi retineo\n" + "lux sto ioco. Per Re dono. Copiose reus scitus jus diligens sis scapulare\n" + "Servitium transi.") + .overloadDoc( + "Lo nam balnearius Opprimo Pennatus, no decentia sui, dicto esse se pulchritudo,\n" + "pupa Sive res indifferenter. Captivo pa.") + .arg("", "Bar didelfrump di desgorb. Nu widsoflar brimeldrgf.") + .arg("checkup", "Florgel, dargel and durgel", 2.1) ); + + dir.add("cb", &cb5) + .overloadDoc( + "Uus Primordia fundo falsidicus corium, diurnitas humo pro leto. Sui Ueraciter\n" + "hio eruca lenis qua Agalmate ut fors penitentia. Iugum obdormio anxio nuncupo\n" + "iam, in vos nam Custodi."); + + (void) cbNode; + dir.add("cb", &cb2); - static_cast(dir("cb")).doc( - "Ops fortunate, ops me ut orgia vociferatio contumax per, rudo re loco emitto\n" - "intolerabiliter ita iugo. Subcribo gravo. Devenio luna fonticulus Castanea\n" - "horum fascino Os interpretor non ipse conjuratio hora, qui filius denuntio ait\n" - "sono te odium Anhelo. Dum Cedo audax celox alius una Agnosco hic, ibi retineo\n" - "lux sto ioco. Per Re dono. Copiose reus scitus jus diligens sis scapulare\n" - "Servitium transi."); + parser.parse("test/cb 111 222.4; test/cb 222; test/cb foo; test/cb", boost::bind( boost::ref(executor), boost::ref(ss), _1 )); BOOST_CHECK_EQUAL( ss.str(), "333\n" "224\n" "Value: foo\n" "1.2\n" ); diff --git a/Console/ScopedDirectory.cti b/Console/ScopedDirectory.cti index 04193e9..2a3664f 100644 --- a/Console/ScopedDirectory.cti +++ b/Console/ScopedDirectory.cti @@ -35,7 +35,7 @@ // senf::console::OwnerNodeCreateTraits::Creator template -prefix_ typename senf::console::OwnerNodeCreateTraits::NodeType & +prefix_ typename senf::console::OwnerNodeCreateTraits::result_type senf::console::OwnerNodeCreateTraits::Creator::create(DirectoryNode & node, Owner & owner, std::string const & name, @@ -56,7 +56,7 @@ prefix_ senf::console::ScopedDirectory::ScopedDirectory(Owner * owner) template template -prefix_ typename senf::console::OwnerNodeCreateTraits::NodeType & +prefix_ typename senf::console::OwnerNodeCreateTraits::result_type senf::console::ScopedDirectory::add(std::string const & name, Object const & ob) { return OwnerNodeCreateTraits::Creator::create(node(), *owner_, name, ob); @@ -90,7 +90,7 @@ senf_console_add_node(DirectoryNode & dir, std::string const & name, Node const // senf::console::ScopedDirectory template -prefix_ typename senf::console::NodeCreateTraits::NodeType & +prefix_ typename senf::console::NodeCreateTraits::result_type senf::console::ScopedDirectory::add(std::string const & name, Object const & ob) { return node().add(name, ob); diff --git a/Console/ScopedDirectory.hh b/Console/ScopedDirectory.hh index e86dc59..c226b2e 100644 --- a/Console/ScopedDirectory.hh +++ b/Console/ScopedDirectory.hh @@ -50,13 +50,15 @@ namespace console { * static_cast(0), * static_cast(0), * static_cast(0), - * static_cast(0)) ) result_type; + * static_cast(0)) ) base_type; + typedef typename senf::remove_cvref::type value_type; - typedef typename boost::remove_reference::type NodeType; + typedef typename value_type::node_type NodeType; + typedef typename value_type::return_type result_type; /// Internal struct Creator { - static NodeType & create(DirectoryNode & node, Owner & owner, + static result_type create(DirectoryNode & node, Owner & owner, std::string const & name, Object const & ob); }; }; @@ -146,8 +148,8 @@ namespace console { /////////////////////////////////////////////////////////////////////////// template - typename OwnerNodeCreateTraits::NodeType & add(std::string const & name, - Object const & ob); + typename OwnerNodeCreateTraits::result_type add(std::string const & name, + Object const & ob); ///< Create new child node /**< Adds a new child node to the (proxied) DirectoryNode. How the node is added is configured @@ -166,8 +168,8 @@ namespace console { { public: template - typename NodeCreateTraits::NodeType & add(std::string const & name, - Object const & ob); + typename NodeCreateTraits::result_type add(std::string const & name, + Object const & ob); }; #ifndef DOXYGEN diff --git a/Utils/Mainpage.dox b/Utils/Mainpage.dox index 49664cf..711946c 100644 --- a/Utils/Mainpage.dox +++ b/Utils/Mainpage.dox @@ -27,7 +27,7 @@ namespace senf { The Utilities Library is a collection of independent utilities. - \section basic_helpers C++ Language helpers and simple library extensions + \section basic_helpers C++ Language helpers and library extensions + +
\ref membinda simple
\ref senfppExtensions to the Boost.Preprocessor library
\ref typetraitsExtensions to the Boost.TypeTraits library
- \section basic_mixins Basic mixin classes + \section basic_mixins Mixin classes
\ref intrusive_refcountmixin to simplify writing classes for use with #include #include +#include +#include #include +#include "../config.hh" #include "type_traits.mpp" ///////////////////////////////hh.p//////////////////////////////////////// -namespace senf { +namespace senf +{ - template + /** \defgroup typetraits Type traits + */ + + ///\addtogroup typetraits + ///\{ + + /** \brief Strip first parameter from function traits + + This meta-function will remove the first argument from \a Traits. The return value is a new + function trait with one less argument. + + If the function described in \a Traits does not take any arguments, it is returned + unchanged. + + \code + typedef boost::function_traits traits + BOOST_STATIC_ASSERT(( boost::is_same< + senf::function_traits_remove_arg< traits >::type, + boost::function_traits + >::value )); + \endcode + + \tparam Traits \c boost::function_traits instantiation + */ + template < class Traits, unsigned arity = Traits::arity > struct function_traits_remove_arg {}; - template - struct remove_member_pointer + /** \brief Get argument type from function traits + + function_traits_arg will return the type of the \a index-th argument from \a + Traits. If the function has no argument at that index, \c void is returned + + \code + typedef boost::function_traits traits; + BOOST_STATIC_ASSERT(( boost:is_same< + senf::function_traits_arg_type< traits, 0 >::type, + int + >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< + senf::function_traits_arg_type< traits, 2 >::type, + void + >::value )); + \endcode + + \tparam Traits \c boost::function_traits instantiation + \tparam index 0 based argument index + */ + template < class Traits, int index, bool flag = (index < Traits::arity) > + struct function_traits_arg_type {}; + +#ifndef DOXYGEN + + template < class Traits, int index > + struct function_traits_arg_type + { + typedef void type; + }; + +#endif + + /** \brief Remove member pointer from type + + This meta function will remove any type of member pointer from it's argument. Other types + will be returned unchanged. + + \code + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_member_pointer< int (Class::*) >::type, + int + >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_member_pointer< void (Class::*)(int) >::type, + void (int) + >::value )); + \endcode + + \tparam MemberPointer type to return member pointer from + */ + template < class MemberPointer > struct remove_member_pointer { typedef MemberPointer type; }; - template - struct remove_member_pointer +#ifndef DOXYGEN + + template < class C, class T > struct remove_member_pointer { typedef T type; }; - template - struct member_class +#endif + + /** \brief Get class of a member pointer + + Returns the class, an arbitrary member pointer belongs to. If the argument is not a member + pointer, void is returned. + + \code + BOOST_STATIC_ASSERT(( boost::is_same< + senf::member_class< int (Class::*) >::type, + Class + >::value )); + BOOST_STATIC_ASSERT(( boost::is_Same< + senf::member_class< int * >::type, + void + >::value )); + \endcode + + \tparam MemberPointer Type to get the member pointer class from + */ + template < class MemberPointer > struct member_class { typedef void type; }; + +#ifndef DOXYGEN - template - struct member_class + template < class C, class T > struct member_class { typedef C type; }; - template +#endif + + /** \brief Remove any type of pointer from type + + This meta function will remove a plain or member pointer from the given type. If \a T is + neither a member pointer nor an ordinary pointer, \a T will be returned unchanged. + + \code + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_any_pointer< int (Class::*) >::type, + int + >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_any_pointer< void (Class::*)(int) >::type, + void (int) > ); + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_any_pointer < int (*)() >::type, + int ( + >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_any_pointer < int >::type, + int + >::value )); + \endcode + + \tparam T type to remove member pointer from + */ + template < class T > struct remove_any_pointer - : public remove_member_pointer::type> + : public remove_member_pointer < typename boost::remove_pointer < T >::type > {}; - template + /** \brief Test object if it is a function or member-function (pointer) + + is_any_function will inherit from \c boost::true_type, when \a T is a function type, + function pointer type or a member function pointer type. Otherwise, it will inherit from \c + boost::false_type. + + \code + BOOST_STATIC_ASSERT(( senf::is_any_function< void () >::value )); + BOOST_STATIC_ASSERT(( senf::is_any_function< void (*)(int) >::value )); + BOOST_STATIC_ASSERT(( senf::is_any_function< void (Class::*)() >::value )); + BOOST_STATIC_ASSERT(( ! senf::is_any_function< int * >::value )); + \endcode + + \tparam T type to test + */ + template < class T > struct is_any_function - : public boost::is_function::type> + : public boost::is_function < typename senf::remove_any_pointer < T >::type > {}; -# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, 10, \ - SENF_ABSOLUTE_INCLUDE_PATH(Utils/type_traits.mpp), \ + /** \brief Remove reference and CV qualification from type + + remove_cvref will remove all the 'ornaments' from a type as typically used to pass + arguments: references and any CV spec. It will thus convert a typical argument type into + it's basic type. + + \code + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_cvref::type, + int + >::value )); + \endcode + */ + template < class T > + struct remove_cvref + : public boost::remove_cv< typename boost::remove_reference::type > + {}; + + ///} + +#ifndef DOXYGEN + +# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, 10, \ + SENF_ABSOLUTE_INCLUDE_PATH(Utils/type_traits.mpp), \ 1)) # include BOOST_PP_ITERATE() +#endif + } ///////////////////////////////hh.e//////////////////////////////////////// @@ -86,8 +251,8 @@ namespace senf { //#include "type_traits.ct" //#include "type_traits.cti" #endif - + // Local Variables: // mode: c++ // fill-column: 100 diff --git a/Utils/type_traits.mpp b/Utils/type_traits.mpp index 8648d7a..9c483da 100644 --- a/Utils/type_traits.mpp +++ b/Utils/type_traits.mpp @@ -35,6 +35,7 @@ #include #include #include +#include // ///////////////////////////mpp.p//////////////////////////////////////// #elif BOOST_PP_IS_ITERATING // //////////////////////////////////////////// @@ -71,6 +72,12 @@ struct member_class typedef C type; }; +template +struct function_traits_arg_type +{ + typedef typename Traits::mpp_Arg(BOOST_PP_ITERATION()) type; +}; + // //////////////////////////////////////////////////////////////////////// #endif // ///////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// diff --git a/Utils/type_traits.test.cc b/Utils/type_traits.test.cc new file mode 100644 index 0000000..34e3c5a --- /dev/null +++ b/Utils/type_traits.test.cc @@ -0,0 +1,120 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief type_traits.test unit tests */ + +//#include "type_traits.test.hh" +//#include "type_traits.test.ih" + +// Custom includes +#include +#include +#include "type_traits.hh" + +#include "../Utils/auto_unit_test.hh" +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + struct Class {}; +} + +BOOST_AUTO_UNIT_TEST(typeTraits) +{ + typedef boost::function_traits traits; + + BOOST_STATIC_ASSERT(( boost::is_same< + senf::function_traits_remove_arg< traits >::type, + boost::function_traits + >::value )); + + BOOST_STATIC_ASSERT(( boost::is_same< + senf::function_traits_arg_type< traits, 0 >::type, + int + >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< + senf::function_traits_arg_type< traits, 2 >::type, + void + >::value )); + + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_member_pointer< int (Class::*) >::type, + int + >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_member_pointer< void (Class::*)(int) >::type, + void (int) + >::value )); + + BOOST_STATIC_ASSERT(( boost::is_same< + senf::member_class< int (Class::*) >::type, + Class + >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< + senf::member_class< int * >::type, + void + >::value )); + + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_any_pointer< int (Class::*) >::type, + int + >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_any_pointer< void (Class::*)(int) >::type, + void (int) + >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_any_pointer < int (*)() >::type, + int () + >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_any_pointer < int >::type, + int + >::value )); + + BOOST_STATIC_ASSERT(( senf::is_any_function< void () >::value )); + BOOST_STATIC_ASSERT(( senf::is_any_function< void (*)(int) >::value )); + BOOST_STATIC_ASSERT(( senf::is_any_function< void (Class::*)() >::value )); + BOOST_STATIC_ASSERT(( ! senf::is_any_function< int * >::value )); + + BOOST_STATIC_ASSERT(( boost::is_same< + senf::remove_cvref::type, + int + >::value )); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: