Automatisches erkennen des Typs bei boost::make_tuple;



  • Hallo,

    folgender Code funktioniert in Visual Studio 2010 nicht:

    int dummyFunc()
    {
      return 0;
    }
    
    typedef function<int(void)> FUNCTYPE; 
    map<string, boost::tuple<int, string, FUNCTYPE>> funcs;
    
    funcs["dummyFunc"] = boost::make_tuple(0, "Dummy-Function", dummyFunc);
    

    Es liefert den Fehler:

    Fehler 12 error C2664: 'boost::tuples::detail::non_storeable_type<T>::non_storeable_type(const boost::tuples::detail::non_storeable_type<T> &)': Konvertierung des Parameters 1 von 'int (__cdecl &)(void)' in 'const boost::tuples::detail::non_storeable_type<T> &' nicht möglich c:\lib\boost\boost\tuple\detail\tuple_basic.hpp 376 1 test

    Dagegen kompiliert folgender Code fehlerfrei:

    int dummyFunc()
    {
      return 0;
    }
    
    typedef function<int(void)> FUNCTYPE; 
    map<string, boost::tuple<int, string, FUNCTYPE>> funcs;
    
    funcs["dummyFunc"] = boost::tuple<int, string, FUNCTYPE>(0, "Dummy-Function", dummyFunc);
    

    Warum liefert make_tuple den Fehler und das direkte Anlegen des Tuples klappt?

    Gruss Uwe



  • wie siehts aus wenn du das string-literal explizit in einen std::string castest?



  • boost::make_tuple weiß anscheinend nichts mit einem Funktions-Lvalue anzufangen. du kannst ja mal probieren, vor dummyFunc den Adress-Operator zu verwenden, also

    boost::make_tuple(0, "Dummy-Function", &dummyFunc)
    

    So oder so erzeugst du ein temporäres Tuple. Um das loszuwerden könntest Du auch schreiben:

    typedef function<int()> func_t;
    typedef boost::tuple<int,string,func_t> tup_t;
    map<string,tup_t> funcs;
    
    tup_t& tup = funcs["dummyFunc"]
    boost::get<0>(tup) = 0;
    boost::get<1>(tup) = "Dummy-Function";
    boost::get<2>(tup) = dummyFunc;
    

    was sich auch in einer eigenen Funktion verpacken ließe.

    Mir ist auch gerade aufgefallen, dass du schon ein C++11 Feature verwendest. Das >> in map<string,boost::tuple<int,string,FUNCTYPE>> ist erst ab C++11 gültig. Um auch C++98/03-kompatibel zu bleiben, müsstest du da ein Leerzeichen einfügen, also > > statt >> . Das hat was mit dem Lexer zu tun, der ein >> wegen der MaxMunch-Regel als Shift-Operator interpretieren würde. Ab C++11 gibt es allerdings auch std::tuple, std::make_tuple, Rvalue-Referenzen und praktische Type Traits. Du könntest Deinen Code ja mal mit std::tuple/make_tuple testen. Das klappt dann vielleicht auch schon.



  • kkaw schrieb:

    Mir ist auch gerade aufgefallen, dass du schon ein C++11 Feature verwendest. Das >> in map<string,boost::tuple<int,string,FUNCTYPE>> ist erst ab C++11 gültig.

    Alle relevanten Compiler haben das alerdings schon sehr viel früher unterstützt auch wenn es eigentlich kein gültiges C++ war.



  • Mit C++11 kann man da richtig auf die K4cke hauen:

    funcs.emplace(std::piecewise_construct,
      std::forward_as_tuple("dummyFunc"),               // <-- Parameter für Key
      std::forward_as_tuple(0,"Dummy-Func",&dummyFunc)  // <-- Parameter für Value
    );
    

    Das müsste das pair -Objekt direkt in der map erzeugen. Ist aber ungetestet.



  • TNA schrieb:

    Alle relevanten Compiler haben das alerdings schon sehr viel früher unterstützt auch wenn es eigentlich kein gültiges C++ war.

    Gegenbeispiel: g++



  • Hallo,

    @kkaw

    Mir ist auch gerade aufgefallen, dass du schon ein C++11 Feature verwendest. Das >> in map<string,boost::tuple<int,string,FUNCTYPE>> ist erst ab C++11 gültig. Um auch C++98/03-kompatibel zu bleiben, müsstest du da ein Leerzeichen einfügen, also > > statt >> .

    das ist mir klar. Aber Visual Studio 2010 unterstützt teilweise C++11 Features. Ich muss nicht zu C++98/03-kompatibel bleiben.

    boost::make_tuple(0, "Dummy-Function", &dummyFunc)

    funktioniert!

    Gruss Uwe


Anmelden zum Antworten