2010-12-22 7 views
15

Ich versuche, eine Liste mit den Permutationen einer bestimmten Typenliste zu erstellen.Permutationen einer Liste von Typen mit boost :: mpl

Der folgende Code scheint zu funktionieren, wenn auch ohne das beabsichtigte Ergebnis, wenn ich eine angegebene Liste verwende, anstatt eine neue Liste durch Entfernen von der tatsächlichen Eingabe zu erstellen. Dies wird durch den Unterschied zwischen permutation_helper und broken_helper unten gezeigt.

Weiß jemand, warum mpl::remove in diesem Fall nicht wie erwartet funktioniert?

Ich habe die Assert verwendet, um zu bestimmen, was von der Funktion zurückgegeben wird, Typeliste ist nicht das erwartete Ergebnis. Dies ist die Botschaft, die die Assertion kehrt für broken_helper:

testcase.cpp: In function ‘int main()’: 
testcase.cpp:45: error: no matching function for call to ‘assertion_failed(mpl_::failed************ boost::mpl::equal<boost::mpl::joint_view<boost::mpl::joint_view<boost::mpl::list0<mpl_::na>, boost::mpl::l_end>, boost::mpl::l_end>, boost::mpl::list2<test_type1, test_type2>, boost::is_same<mpl_::arg<-0x00000000000000001>, mpl_::arg<-0x00000000000000001> > >::************)’ 

Der Ausgang permutation_helper verwendet, ist eine aktuelle Liste:

testcase.cpp: In function ‘int main()’: 
testcase.cpp:45: error: no matching function for call to ‘assertion_failed(mpl_::failed************ boost::mpl::equal<boost::mpl::list2<test_type1, test_type2>, boost::mpl::joint_view<boost::mpl::joint_view<boost::mpl::list0<mpl_::na>, boost::mpl::l_item<mpl_::long_<1l>, boost::mpl::l_item<mpl_::long_<2l>, test_type1, boost::mpl::list1<test_type3> >, boost::mpl::l_end> >, boost::mpl::l_item<mpl_::long_<1l>, boost::mpl::l_item<mpl_::long_<2l>, test_type2, boost::mpl::list1<test_type3> >, boost::mpl::l_end> >, boost::is_same<mpl_::arg<-0x00000000000000001>, mpl_::arg<-0x00000000000000001> > >::************)’ 

Antwort

5

mpl::remove funktioniert ordnungsgemäß. Das Problem ist mit Ihrer Vorlage für Permutationen von Singleton-Listen: Es fängt nur Typen ein, die mpl::list s sind, während das Ergebnis von Entfernen einen anderen Sequenztyp hat.

Mit anderen Worten, das Ergebnis mpl::remove ist mpl::equal auf die Singleton Liste, aber nicht std::is_same:

#include <boost/mpl/list.hpp> 
#include <boost/mpl/remove.hpp> 
#include <boost/mpl/equal.hpp> 

namespace mpl = boost::mpl; 

struct test_type1 {}; 
struct test_type2 {}; 

typedef mpl::list2<test_type1, test_type2> typelist; 
typedef mpl::remove<typelist, test_type1>::type t; 
typedef mpl::list1<test_type2> t_corr; 

static_assert(mpl::equal<t,t_corr>::value, "t equals t_corr"); 
// the following will fail: 
// static_assert(std::is_same<t,t_corr>::value, "t same type as t_corr"); 

int main() { 
    return 0; 
} 

Sie dieses Problem beheben können Sie Ihre Vorlage für die Singleton-Liste nicht auf die genaue Art von Spezialisierung mpl::list , aber auf dem Grundstück haben Länge 1:

#include <boost/mpl/list.hpp> 
#include <boost/mpl/transform.hpp> 
#include <boost/mpl/fold.hpp> 
#include <boost/mpl/push_front.hpp> 
#include <boost/mpl/joint_view.hpp> 
#include <boost/mpl/remove.hpp> 
#include <boost/mpl/assert.hpp> 
#include <boost/mpl/equal.hpp> 
#include <boost/mpl/size.hpp> 
#include <boost/mpl/front.hpp> 
#include <boost/mpl/begin.hpp> 
#include <boost/mpl/next.hpp> 

namespace mpl = boost::mpl; 

struct test_type1 {}; 
struct test_type2 {}; 
struct test_type3 {}; 

template< typename T, typename _ENABLE=void > 
struct permutations; 

template <typename T> 
struct permutations<T, 
      typename std::enable_if<mpl::size<T>::value==1>::type> 
{ 
    typedef typename mpl::list1<T> type; 
}; 

template< typename value, typename T> 
struct permutation_helper: 
     mpl::transform< typename permutations< 
     mpl::list1<test_type3> >::type, 
    mpl::push_front< mpl::_1, value> > { }; 

template< typename value, typename T> 
struct broken_helper: 
    mpl::transform< typename permutations< 
      typename mpl::remove<T, value>::type >::type, 
      mpl::push_front< mpl::_1, value> > { }; 

template< typename T > 
struct permutations<T, 
      typename std::enable_if<(mpl::size<T>::value>1)>::type>: 
    mpl::fold< T, 
     mpl::list0<>, 
     mpl::joint_view< mpl::_1, 
     broken_helper<mpl::_2, T > > > { }; 

typedef mpl::list2<test_type1, test_type2> typelist; 
typedef permutations<typelist>::type perms; 
typedef mpl::list<mpl::list<test_type1, test_type2>, 
      mpl::list<test_type2, test_type1> > perms_corr; 

int main() { 
    static_assert(mpl::size<perms>::value == 2, "perms has correct size"); 
    static_assert(mpl::equal<mpl::front<perms>::type, 
        mpl::front<perms_corr>::type>::value, "perms has correct front"); 
    typedef mpl::next<mpl::begin<perms>::type>::type perms_2nd; 
    typedef mpl::next<mpl::begin<perms_corr>::type>::type perms_corr_2nd; 
    static_assert(mpl::equal<perms_2nd, perms_corr_2nd>::value, "perms has correct 2nd element"); 
    return 0; 
} 

By the way,

static_assert(mpl::equal<perms, perms_corr>::value, "perms correct"); 

wird aus genau den gleichen Gründen fehlschlagen.

  • lars
-3

Haben Sie versucht, den Code als zugehörig zu dem entsprechenden Namensraum der Bibliothek setzen?

Es klingt vielleicht dumm, aber da ich bereits ein ähnliches Problem gelöst habe (aber nicht mit MPL!).

3

Als Nachtrag zu der Antwort, die Lars posted:

Der Algorithmus gegeben Permutation joint_view Verwendung scheint nicht mit einer Größe von mehr als zwei auf einer Liste zu arbeiten. Ich ersetzte es mit einem mpl :: copy in einen front_inserter, und der Algorithmus funktionierte perfekt.

#include <boost/mpl/copy.hpp> 
#include <boost/mpl/front_inserter.hpp> 

template< typename T > 
struct permutations<T, typename std::enable_if<(mpl::size<T>::value>1)>::type> : 
    mpl::fold< T, 
      mpl::list0<>, 
      mpl::copy< broken_helper< mpl::_2, T >, 
       mpl::front_inserter<mpl::_1> > > { }; 
Verwandte Themen