Menu

AttributeSetProvider.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2008-2010 Michael Schulze <mschulze@ivs.cs.uni-magdeburg.de>
00004  *                    2010 Marcus Foerster <MarcusFoerster1@gmx.de>
00005  * All rights reserved.
00006  *
00007  *    Redistribution and use in source and binary forms, with or without
00008  *    modification, are permitted provided that the following conditions
00009  *    are met:
00010  *
00011  *    * Redistributions of source code must retain the above copyright
00012  *      notice, this list of conditions and the following disclaimer.
00013  *
00014  *    * Redistributions in binary form must reproduce the above copyright
00015  *      notice, this list of conditions and the following disclaimer in
00016  *      the documentation and/or other materials provided with the
00017  *      distribution.
00018  *
00019  *    * Neither the name of the copyright holders nor the names of
00020  *      contributors may be used to endorse or promote products derived
00021  *      from this software without specific prior written permission.
00022  *
00023  *
00024  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00025  *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00026  *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00027  *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  *    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  *    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  *    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  *    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  *    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  *    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  *
00037  * $Id$
00038  *
00039  ******************************************************************************/
00040 
00041 #ifndef _Set_Provider_h_
00042 #define _Set_Provider_h_
00043 
00044 #include "boost/mpl/aux_/na.hpp"
00045 #include "boost/utility/enable_if.hpp"
00046 #include "boost/mpl/vector.hpp"
00047 #include "boost/mpl/is_sequence.hpp"
00048 #include "boost/mpl/sort.hpp"
00049 #include "boost/mpl/eval_if.hpp"
00050 #include "boost/mpl/bool.hpp"
00051 
00052 #include "mw/attributes/AttributeSet.h"
00053 #include "mw/attributes/type_traits/is_attribute.h"
00054 
00055 #include "assert/staticerror.h"
00056 
00057 namespace famouso {
00058     namespace mw {
00059         namespace attributes {
00060             namespace detail {
00069                 template <typename Attr, typename InnerEnable = void>
00070                 struct assert_is_attribute_or_na  {
00071                         FAMOUSO_STATIC_ASSERT_ERROR(
00072                             false,
00073                             template_argument_no_attribute_and_not_na,
00074                             (Attr));
00075 
00076                         typedef void type;
00077                 };
00078 
00079                 template <>
00080                 struct assert_is_attribute_or_na<boost::mpl::na, void> {
00081                         typedef void type;
00082                 };
00083 
00084                 template <typename Attr>
00085                 struct assert_is_attribute_or_na<
00086                         Attr,
00087                         typename boost::enable_if<
00088                                         famouso::mw::attributes::type_traits::is_attribute<
00089                                                                                Attr
00090                                                                               >
00091                                        >::type
00092                        > {
00093                         typedef void type;
00094                 };
00095 
00096                 template <typename T>
00097                 struct is_sequence : boost::mpl::is_sequence<T> { };
00098 
00099                 template <>
00100                 struct is_sequence<boost::mpl::na> {
00101                         typedef is_sequence type;
00102 
00103                         static const bool value = false;
00104                 };
00105 
00106                 struct SorterPredicate {
00107                         // For both types being attributes
00108                         template <typename A1, typename A2>
00109                         struct apply {
00110                                 static const bool value = A1::id > A2::id;
00111 
00112                                 typedef apply type;
00113                         };
00114 
00115                         // For only the first type being an attribute
00116                         template <typename T1>
00117                         struct apply<T1, boost::mpl::na> {
00118                                 static const bool value = true;
00119 
00120                                 typedef apply type;
00121                         };
00122 
00123                         // For only the second type being an attribute
00124                         template <typename T2>
00125                         struct apply<boost::mpl::na, T2> : public apply<T2, boost::mpl::na> {};
00126 
00127                         typedef SorterPredicate type;
00128                 };
00129 
00130                 template <typename Seq>
00131                 struct SortedAttributeSequence {
00132                         typedef typename boost::mpl::sort<Seq, SorterPredicate>::type result;
00133 
00134                         typedef SortedAttributeSequence type;
00135                 };
00136 
00167                 template <typename A1 = boost::mpl::na, typename A2 = boost::mpl::na,
00168                           typename A3 = boost::mpl::na, typename A4 = boost::mpl::na,
00169                           typename A5 = boost::mpl::na, typename A6 = boost::mpl::na,
00170                           typename A7 = boost::mpl::na, typename A8 = boost::mpl::na,
00171                           typename A9 = boost::mpl::na, typename A10 = boost::mpl::na,
00172                           typename Enable = void>
00173                 struct SetProvider {
00174                         // Primary template implements the case that all given types
00175                         //  are attributes
00176 
00177                     private:
00178                         // Apply the assertion to all of the given types
00179 
00180                         typedef typename assert_is_attribute_or_na<A1>::type  aa1;
00181                         typedef typename assert_is_attribute_or_na<A2>::type  aa2;
00182                         typedef typename assert_is_attribute_or_na<A3>::type  aa3;
00183                         typedef typename assert_is_attribute_or_na<A4>::type  aa4;
00184                         typedef typename assert_is_attribute_or_na<A5>::type  aa5;
00185                         typedef typename assert_is_attribute_or_na<A6>::type  aa6;
00186                         typedef typename assert_is_attribute_or_na<A7>::type  aa7;
00187                         typedef typename assert_is_attribute_or_na<A8>::type  aa8;
00188                         typedef typename assert_is_attribute_or_na<A9>::type  aa9;
00189                         typedef typename assert_is_attribute_or_na<A10>::type aa10;
00190 
00191                         // If none of the assertions was violated, define a vector
00192                         //  containing the given attribute types
00193                         typedef typename SortedAttributeSequence<
00194                                           boost::mpl::vector<A1, A2, A3, A4, A5,
00195                                                    A6, A7, A8, A9, A10
00196                                           >
00197                                          >::result attribs;
00198 
00199                     public:
00203                         typedef attributes::AttributeSet<attribs> attrSet;
00204                 };
00205 
00206                 template <typename ForwardSeq>
00207                 struct SetProvider<ForwardSeq, boost::mpl::na, boost::mpl::na,
00208                                         boost::mpl::na, boost::mpl::na, boost::mpl::na,
00209                                         boost::mpl::na, boost::mpl::na, boost::mpl::na,
00210                                         boost::mpl::na,
00211                                         typename boost::enable_if<
00212                                                          is_sequence<ForwardSeq>
00213                                                         >::type> {
00214                         // Specialized template cares for the case that only a forward
00215                         //  sequence of attributes is given as the first type
00216 
00217                         typedef typename SortedAttributeSequence<
00218                                           ForwardSeq
00219                                          >::result attribs;
00220 
00221                     public:
00225                         typedef attributes::AttributeSet<attribs> attrSet;
00226                 };
00227 
00228             }  // end namespace detail
00229         }  // end namespace attributes
00230     }  // end namespace mw
00231 }  // end namespace famouso
00232 
00233 #endif // _Set_Provider_