Set mit Values einer Map initialisieren



  • Hi,

    ich würde gerne eine Variable s vom Typ set<int> mit den Values einer Variable m vom Typ map<unsigned, int> initialisieren. Wenn also m die Key-Value-Paare 0 -> 1, 2 -> 3, 4 -> 3, 5 -> -1 enthält, soll s mit {1, 3, -1} initialisiert werden. Geht das irgendwie mit einem Einzeiler?



  • Mit Lambda-Ausdrücken:

    #include <set>
    #include <map>
    #include <iterator>
    #include <algorithm>
    
    int main()
    {
    	std::map<int, int> m;
    	m[0] = 1;
    	m[2] = 3;
    	m[4] = 3;
    	m[5] = -1;
    
    	std::set<int> s;
    	std::transform(m.begin(), m.end(), std::inserter(s, s.begin()), [](std::pair<int, int> p) { return p.second; });
    }
    

    Mit C++98 sehe ich gerade keine einzeilige Lösung, da mir nichts Vorgefertigtes zur Extraktion von second aus pair einfällt...



  • ingobulla schrieb:

    Geht das irgendwie mit einem Einzeiler?

    Wenn man von includes absieht geht fast alles mit einem Einzeiler...

    "Zweizeiler":

    #include <set>
    #include <map>
    #include <iterator>
    #include <algorithm>
    
    int main()
    {
        std::map<int, int> m;
        m[0] = 1;
        m[2] = 3;
        m[4] = 3;
        m[5] = -1;
    
        std::set<int> s;
        struct {int operator()(std::pair<int, int> p) { return p.second; }} seconder;
        std::transform(m.begin(), m.end(), std::inserter(s, s.begin()), seconder);
    }
    

    technisch ein Einzeiler:

    #include <set>
    #include <map>
    #include <iterator>
    #include <algorithm>
    
    int main()              \
    { \
        std::map<int, \
    int> m; \
        m[0] = \
    1; \
        m[2] = 3;\
        m[4] = 3;          \
        m[5] = -1;\
    \
        std::set<int> s;   \
        struct   \
     {int \
     operator() \
    (std::pair<int, int> p) \
    { return p.second; \
    }} seconder;\
        std::transform\
                                 (m.begin(), m.end(),         \
    std::inserter(s, \
    s.begin()), seconder);    \
    }
    

    oder so

    #include <set>
    #include <map>
    #include <iterator>
    #include <algorithm>
    int main(){std::map<int,int>m;m[0]=1;m[2]=3;m[4]=3;m[5]=-1;std::set<int>s;struct{int operator()(std::pair<int,int>p){return p.second;}}seconder;std::transform(m.begin(),m.end(),std::inserter(s,s.begin()),seconder);}
    


  • pumuckl schrieb:

    [...]

    Wenn ich recht entsinne, durfte man lokal definierte Klassen nicht als Template-Argument benutzen. Mag aber auch sein, dass ich mich täusche.



  • MSVC hats gefressen, gcc 4.1.2 (codepad.org) nicht - ist natürlich kein Argument, weder dafür noch dagegen. Ich belese mich mal...



  • Soweit ich weiss, ist das ab C++0x erlaubt.



  • pumuckl schrieb:

    MSVC hats gefressen, gcc 4.1.2 (codepad.org) nicht - ist natürlich kein Argument, weder dafür noch dagegen. Ich belese mich mal...

    Nachtrag:

    ISO/IEC 14882, §14.3.1,2 schrieb:

    A local type [...] shall not be used as a template-argument for a template type-parameter.

    Darf also nicht...



  • Nexus schrieb:

    Soweit ich weiss, ist das ab C++0x erlaubt.

    Jup.

    Working draft N3225, §14.3.1,2 schrieb:

    [Example:

    template <class T> class X;
    template <class T> void f(T t) {}
    struct {} unnamed_obj;
    
    void f() {
      struct A {};
      enum { e1 };
      typedef struct {} B;
      B b;
      X<A> x1;          //OK
      X<A*> x2;         //OK
      X<B> x3;          //OK
      f(e1);            //OK
      f(unnamed_obj);   //OK
      f(b);             //OK
    }
    

    -- end example][Note: a template argument may be an incomplete type (3.9). -- end note]

    Zeile 14 wäre das, was in meinem Code oben nach C++98 noch verboten ist...


Anmelden zum Antworten