Utils: Add unit-test and documentation for type_traits.hh
g0dil [Wed, 9 Apr 2008 18:56:16 +0000 (18:56 +0000)]
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

15 files changed:
Console/Node.cti
Console/Node.hh
Console/OverloadedCommand.hh
Console/ParsedCommand.cci
Console/ParsedCommand.cti
Console/ParsedCommand.hh
Console/ParsedCommand.mpp
Console/ParsedCommand.test.cc
Console/ScopedDirectory.cti
Console/ScopedDirectory.hh
Utils/Mainpage.dox
Utils/mpl.hh
Utils/type_traits.hh
Utils/type_traits.mpp
Utils/type_traits.test.cc [new file with mode: 0644]

index ef80237..69baef1 100644 (file)
@@ -34,7 +34,7 @@
 // senf::console::NodeCreateTraits<Object>::Creator
 
 template <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::NodeType &
+prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
 senf::console::NodeCreateTraits<Object>::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 <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::NodeType &
+prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
 senf::console::DirectoryNode::add(std::string const & name, Object const & ob)
 {
     return NodeCreateTraits<Object>::Creator::create(*this, name, ob);
index 29c5511..9bf37ec 100644 (file)
 #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<DirectoryNode *>(0),
                                       * static_cast<std::string const *>(0),
                                       * static_cast<Object const *>(0),
-                                      0) ) result_type;
+                                      0) ) base_type;
+        typedef typename senf::remove_cvref<base_type>::type value_type;
 
-        typedef typename boost::remove_reference<result_type>::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<ChildMap::const_iterator> 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 <class Object>
-        typename NodeCreateTraits<Object>::NodeType & add (std::string const & name, 
-                                                           Object const & ob);
+        typename NodeCreateTraits<Object>::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<void (std::ostream &, ParseCommandInfo const &)> Function;
 
+        typedef SimpleCommandNode node_type;
+        typedef SimpleCommandNode & return_type;
+
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
         ///\{
index 48b1097..e7b5692 100644 (file)
@@ -138,6 +138,9 @@ namespace console {
         typedef boost::shared_ptr<OverloadedCommandNode const> cptr;
         typedef boost::weak_ptr<OverloadedCommandNode> weak_ptr;
 
+        typedef OverloadedCommandNode node_type;
+        typedef OverloadedCommandNode & return_type;
+
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
         ///@{
index 94bbf32..0317002 100644 (file)
@@ -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_
 
index 60b7fde..6809191 100644 (file)
@@ -58,6 +58,122 @@ prefix_ void senf::console::ParsedCommandOverloadBase::addParameter()
 #include BOOST_PP_ITERATE()
 
 ///////////////////////////////////////////////////////////////////////////
+// senf::console::ParsedCommandAttributorBase
+
+template <class Type>
+prefix_ void senf::console::ParsedCommandAttributorBase::defaultValue(Type const & value)
+    const
+{
+    overload().arg<Type>(index_).defaultValue = value;
+    overload().arg(index_).hasDefault = true;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ParsedCommandAttributor<Overload>
+
+template <class Overload>
+prefix_ Overload & senf::console::ParsedCommandAttributor<Overload>::overload()
+    const
+{
+    return static_cast<Overload &>(ParsedCommandAttributorBase::overload());
+}
+
+template <class Overload>
+prefix_
+senf::console::ParsedCommandAttributor<Overload>::ParsedCommandAttributor(Overload & overload,
+                                                                          unsigned index)
+    : ParsedCommandAttributorBase (overload, index)
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ParsedAttributeAttributorBase<Overload,Self>
+
+template <class Overload, class Self>
+prefix_ Self
+senf::console::ParsedAttributeAttributorBase<Overload,Self>::doc(std::string const & doc)
+    const
+{
+    this->ParsedCommandAttributorBase::nodeDoc(doc);
+    return static_cast<Self const &>(*this);
+}
+
+template <class Overload, class Self>
+prefix_ Self senf::console::ParsedAttributeAttributorBase<Overload,Self>::
+overloadDoc(std::string const & doc)
+    const
+{
+    this->ParsedCommandAttributorBase::overloadDoc(doc);
+    return static_cast<Self const &>(*this);
+}
+
+template <class Overload, class Self>
+prefix_
+senf::console::ParsedAttributeAttributorBase<Overload,Self>::
+ParsedAttributeAttributorBase(Overload & overload, unsigned index)
+    : ParsedCommandAttributor<Overload> (overload, index)
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ParsedAttributeAttributor<Overload,index,flag>
+
+template <class Overload, unsigned index, bool flag>
+prefix_ senf::console::ParsedAttributeAttributor<Overload, index+1>
+senf::console::ParsedAttributeAttributor<Overload,index,flag>::arg(std::string const & name,
+                                                                   std::string const & doc)
+    const
+{
+    this->argName(name);
+    this->argDoc(doc);
+    return next();
+}
+
+template <class Overload, unsigned index, bool flag>
+prefix_ senf::console::ParsedAttributeAttributor<Overload, index+1>
+senf::console::ParsedAttributeAttributor<Overload,index,flag>::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 <class Overload, unsigned index, bool flag>
+prefix_
+senf::console::ParsedAttributeAttributor<Overload,index,flag>::
+ParsedAttributeAttributor(Overload & overload)
+    : ParsedAttributeAttributorBase<Overload, ParsedAttributeAttributor> (overload, index)
+{}
+
+template <class Overload, unsigned index, bool flag>
+prefix_ senf::console::ParsedAttributeAttributor<Overload, index+1>
+senf::console::ParsedAttributeAttributor<Overload,index,flag>::next()
+    const
+{
+    return ParsedAttributeAttributor<Overload, index+1>(this->overload());
+}
+
+template <class Overload, unsigned index, bool flag>
+prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
+defaultValue(value_type const & value)
+    const
+{
+    ParsedCommandAttributorBase::defaultValue<arg_type>(value);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ParsedAttributeAttributor<Overload, index, false>
+
+template <class Overload, unsigned index>
+prefix_
+senf::console::ParsedAttributeAttributor<Overload, index, false>::
+ParsedAttributeAttributor(Overload & overload)
+    : ParsedAttributeAttributorBase<Overload, ParsedAttributeAttributor> (overload, index)
+{}
+
+///////////////////////////////////////////////////////////////////////////
 // namespace members
 
 namespace {
@@ -98,8 +214,9 @@ namespace {
 }
 
 template <class Function>
-prefix_ senf::console::ParsedCommandOverload<
-    typename senf::console::detail::ParsedCommandTraits<Function>::traits> &
+prefix_ senf::console::ParsedAttributeAttributor<
+    senf::console::ParsedCommandOverload<
+        typename senf::console::detail::ParsedCommandTraits<Function>::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<OverloadedCommandNode &>(node(name))
         : node.add(name, OverloadedCommandNode::create()) );
 
-    typedef senf::console::detail::ParsedCommandTraits<Function> CmdTraits;
+    typedef detail::ParsedCommandTraits<Function> CmdTraits;
+    typedef ParsedCommandOverload<typename CmdTraits::traits> Overload;
+    typedef ParsedAttributeAttributor<Overload> 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 <class Owner, class Function>
-prefix_ senf::console::ParsedCommandOverload<
-    typename senf::console::detail::ParsedCommandTraits<Function>::traits> &
+prefix_ senf::console::ParsedAttributeAttributor<
+    senf::console::ParsedCommandOverload<
+        typename senf::console::detail::ParsedCommandTraits<Function>::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<OverloadedCommandNode &>(node(name))
         : node.add(name, OverloadedCommandNode::create()) );
 
-    typedef senf::console::detail::ParsedCommandTraits<Function> CmdTraits;
+    typedef detail::ParsedCommandTraits<Function> CmdTraits;
+    typedef ParsedCommandOverload<typename CmdTraits::traits> Overload;
+    typedef ParsedAttributeAttributor<Overload> 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///////////////////////////////////////
index 70f4203..020fe6f 100644 (file)
@@ -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 <class Type> 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 Overload>
+    class ParsedCommandAttributor
+        : public ParsedCommandAttributorBase
+    {
+    public:
+        Overload & overload() const;
+
+    protected:
+        ParsedCommandAttributor(Overload & overload, unsigned index);
+
+    private:
+    };
+
+    template <class Overload, class Self>
+    class ParsedAttributeAttributorBase
+        : public ParsedCommandAttributor<Overload>
+    {
+    public:
+        Self doc(std::string const & doc) const;
+        Self overloadDoc(std::string const & doc) const;
+
+    protected:
+        ParsedAttributeAttributorBase(Overload & overload, unsigned index);
+
+    private:
+    };
+
+    template <class Overload, unsigned index=0, bool flag=(index < unsigned(Overload::traits::arity))>
+    class ParsedAttributeAttributor
+        : public ParsedAttributeAttributorBase< Overload, 
+                                                ParsedAttributeAttributor<Overload, index, flag> >
+    {
+    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<Overload, index+1> arg(std::string const & name = "",
+                                                         std::string const & doc = "") const;
+        ParsedAttributeAttributor<Overload, index+1> arg(std::string const & name,
+                                                         std::string const & doc,
+                                                         value_type const & value) const;
+
+    private:
+        explicit ParsedAttributeAttributor(Overload & overload);
+
+        ParsedAttributeAttributor<Overload, index+1> next() const;
+
+        void defaultValue(value_type const & value) const;
+
+        template <class O, unsigned i, bool f>
+        friend class ParsedAttributeAttributor;
+        
+        template <class Function>
+        friend ParsedAttributeAttributor<
+            ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
+        senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
+        
+        template <class Owner, class Function>
+        friend ParsedAttributeAttributor<
+            ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
+        senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
+                              Function fn, int,
+                              typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
+    };
+
+    template <class Overload, unsigned index>
+    class ParsedAttributeAttributor<Overload, index, false>
+        : public ParsedAttributeAttributorBase< Overload, 
+                                                ParsedAttributeAttributor<Overload, index, false> >
+    {
+    public:
+        typedef OverloadedCommandNode node_type;
+        typedef ParsedAttributeAttributor return_type;
+
+    private:
+        explicit ParsedAttributeAttributor(Overload & overload);
+
+        template <class O, unsigned i, bool f>
+        friend class ParsedAttributeAttributor;
+        
+        template <class Function>
+        friend ParsedAttributeAttributor<
+            ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
+        senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
+        
+        template <class Owner, class Function>
+        friend ParsedAttributeAttributor<
+            ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
+        senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
+                              Function fn, int,
+                              typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
+    };
+
 #ifndef DOXYGEN
 
     template <class Function>
-    ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> &
+    ParsedAttributeAttributor<
+        ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
     senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
 
     template <class Owner, class Function>
-    ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> &
+    ParsedAttributeAttributor<
+        ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
     senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
                           Function fn, int,
                           typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::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////////////////////////////////////////
index 2aadffc..b2830ea 100644 (file)
@@ -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
 
index 5b90f2c..b7c78d6 100644 (file)
@@ -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<double>(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<senf::console::OverloadedCommandNode&>(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<void>( boost::ref(executor), boost::ref(ss), _1 ));
         BOOST_CHECK_EQUAL( ss.str(), "333\n" "224\n" "Value: foo\n" "1.2\n" );
index 04193e9..2a3664f 100644 (file)
@@ -35,7 +35,7 @@
 // senf::console::OwnerNodeCreateTraits<Owner,Object>::Creator
 
 template <class Owner, class Object>
-prefix_ typename senf::console::OwnerNodeCreateTraits<Owner,Object>::NodeType &
+prefix_ typename senf::console::OwnerNodeCreateTraits<Owner,Object>::result_type
 senf::console::OwnerNodeCreateTraits<Owner,Object>::Creator::create(DirectoryNode & node,
                                                                     Owner & owner,
                                                                     std::string const & name,
@@ -56,7 +56,7 @@ prefix_ senf::console::ScopedDirectory<Owner>::ScopedDirectory(Owner * owner)
 
 template <class Owner>
 template <class Object>
-prefix_ typename senf::console::OwnerNodeCreateTraits<Owner, Object>::NodeType &
+prefix_ typename senf::console::OwnerNodeCreateTraits<Owner, Object>::result_type
 senf::console::ScopedDirectory<Owner>::add(std::string const & name, Object const & ob)
 {
     return OwnerNodeCreateTraits<Owner, Object>::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<void>
 
 template <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::NodeType &
+prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
 senf::console::ScopedDirectory<void>::add(std::string const & name, Object const & ob)
 {
     return node().add(name, ob);
index e86dc59..c226b2e 100644 (file)
@@ -50,13 +50,15 @@ namespace console {
                                       * static_cast<Owner *>(0),
                                       * static_cast<std::string const *>(0),
                                       * static_cast<Object const *>(0),
-                                      * static_cast<int *>(0)) ) result_type;
+                                      * static_cast<int *>(0)) ) base_type;
+        typedef typename senf::remove_cvref<base_type>::type value_type;
 
-        typedef typename boost::remove_reference<result_type>::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 <class Object>
-        typename OwnerNodeCreateTraits<Owner, Object>::NodeType & add(std::string const & name,
-                                                                      Object const & ob);
+        typename OwnerNodeCreateTraits<Owner, Object>::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 <class Object>
-        typename NodeCreateTraits<Object>::NodeType & add(std::string const & name,
-                                                          Object const & ob);
+        typename NodeCreateTraits<Object>::result_type add(std::string const & name,
+                                                           Object const & ob);
     };
 
 #ifndef DOXYGEN
index 49664cf..711946c 100644 (file)
@@ -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
 
     <table class="listing">
     <tr><td>\ref membind</td><td>a simple <a
@@ -37,10 +37,12 @@ namespace senf {
     tasks</td></tr>
 
     <tr><td>\ref senfpp</td><td>Extensions to the Boost.Preprocessor library</td></tr>
+
+    <tr><td>\ref typetraits</td><td>Extensions to the Boost.TypeTraits library</td></tr>
     </table>
 
 
-    \section basic_mixins Basic mixin classes
+    \section basic_mixins Mixin classes
     
     <table class="listing">
     <tr><td>\ref intrusive_refcount</td><td>mixin to simplify writing classes for use with <a
index 02cf225..5f17c68 100644 (file)
@@ -45,6 +45,7 @@ namespace mpl {
         to mark missing arguments 
         
         \note Don't use this as an empty base class. We may add some informative members to this.
+        \ingroup senfmpl
      */
     struct nil {};
 
index bbf56a5..8ee2429 100644 (file)
 #include <boost/type_traits/function_traits.hpp>
 #include <boost/type_traits/remove_pointer.hpp>
 #include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
 #include <boost/bind.hpp>
+#include "../config.hh"
 
 #include "type_traits.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
 
-namespace senf {
+namespace senf
+{
 
-    template <class Traits, unsigned arity=Traits::arity>
+    /** \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<void (int, double)> traits
+        BOOST_STATIC_ASSERT(( boost::is_same< 
+            senf::function_traits_remove_arg< traits >::type, 
+            boost::function_traits<void (double)> 
+        >::value ));
+        \endcode
+
+        \tparam Traits \c boost::function_traits instantiation
+     */
+    template < class Traits, unsigned arity = Traits::arity >
     struct function_traits_remove_arg {};
 
-    template <class MemberPointer>
-    struct remove_member_pointer
+    /** \brief Get argument type from function traits
+        
+        function_traits_arg<Traits, index> 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<void (int, double)> 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 <Traits, index, false >
+    {
+        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 <class C, class T>
-    struct remove_member_pointer<T (C::*)>
+#ifndef DOXYGEN
+
+    template < class C, class T > struct remove_member_pointer <T (C::*) >
     {
         typedef T type;
     };
 
-    template <class MemberPointer>
-    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 <class C, class T>
-    struct member_class<T (C::*)>
+    template < class C, class T > struct member_class <T (C::*) >
     {
         typedef C type;
     };
 
-    template <class T>
+#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<typename boost::remove_pointer<T>::type>
+        : public remove_member_pointer < typename boost::remove_pointer < T >::type >
     {};
 
-    template <class T>
+    /** \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<typename senf::remove_any_pointer<T>::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<int const &>::type,
+            int
+        >::value ));
+        \endcode
+     */
+    template < class T >
+    struct remove_cvref
+        : public boost::remove_cv< typename boost::remove_reference<T>::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
-
 \f
+
 // Local Variables:
 // mode: c++
 // fill-column: 100
index 8648d7a..9c483da 100644 (file)
@@ -35,6 +35,7 @@
 #include <boost/preprocessor/punctuation/comma_if.hpp>
 #include <boost/preprocessor/arithmetic/dec.hpp>
 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
 
 // ///////////////////////////mpp.p////////////////////////////////////////
 #elif BOOST_PP_IS_ITERATING // ////////////////////////////////////////////
@@ -71,6 +72,12 @@ struct member_class<RV (C::*)(BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), A ))>
     typedef C type;
 };
 
+template <class Traits>
+struct function_traits_arg_type<Traits, BOOST_PP_ITERATION(), true>
+{
+    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 (file)
index 0000000..34e3c5a
--- /dev/null
@@ -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 <g0dil@berlios.de>
+//
+// 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 <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include "type_traits.hh"
+
+#include "../Utils/auto_unit_test.hh"
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+    struct Class {};
+}
+
+BOOST_AUTO_UNIT_TEST(typeTraits)
+{
+    typedef boost::function_traits<void (int, double)> traits;
+
+    BOOST_STATIC_ASSERT(( boost::is_same< 
+        senf::function_traits_remove_arg< traits >::type, 
+        boost::function_traits<void (double)> 
+    >::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<int const &>::type,
+        int
+    >::value ));
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// 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: