variadische funktion



  • ich arbeite aktuell bei einer kleinen funktionensammlung zum thema interpolationen (jaja rad neu erfinden und so...).

    ich arbeite mit einem klassentemplate node, bei welchem man den datentyp, die dimensionen, die position und die auflösung einstellen kann.

    für eine angenehmere bedienung habe ich eine funktion makenode gemacht, die eine variadische templatefunktion ist.

    mein kleinstes kompilierbares beispiel:

    #include <vector>
    #include <cstdlib>
    #include <cstdarg>
    #include <iterator>
    #include <iostream>
    namespace Interpolation
    {
        unsigned long DefaultRes = 1;
        template<class T, unsigned D>
        struct Node
        {
            Node(T const *Data, unsigned long Resolution = DefaultRes);
            T Data[D];
            unsigned long Resolution;
        };
        template<class T, unsigned D>
        Node<T, D> MakeNode(T First, ...);
    }
    template<class T, unsigned D>
    Interpolation::Node<T, D>::Node(T const *Data, unsigned long Resolution)
    : Resolution(Resolution)
    {
        for(unsigned i = 0; i < D; i++)
            this->Data[i] = Data[i];
    }
    template<class T, unsigned D>
    Interpolation::Node<T, D>
    Interpolation::MakeNode(T First, ...)
    {
        T Data[D] = {First};
        va_list Args;
        va_start(Args, First);
        for(unsigned i = 1; i < D; i++)
            Data[i] = va_arg(Args, T);
        va_end(Args);
        return Interpolation::Node<T, D>(Data);
    }
    int main()
    {
        using Interpolation::MakeNode;
        std::vector< ::Interpolation::Node<float, 2> > Data;
        Data.push_back(MakeNode<float, 2>(5, 5));
        std::cout << Data.front().Data[0] << ' ' << Data.front().Data[1];
    }
    

    dieser code kompiliert, jedoch bekomme ich einen runtime error:
    http://ideone.com/TPaMLe

    result: runtime error time: 0s memory: 2892 kB signal: 4 (SIGILL)

    ich kann mir diesen runtime error nicht erklären, ich hab den teil mit der variadik neu geschrieben um allenfällige tippfehler die mir nicht aufgefallen sind auszuschliessen, mit dem selben ergebnis.


  • Mod

    test.cpp: In function ‘Interpolation::Node<T, D> Interpolation::MakeNode(T, ...) [with T = float; unsigned int D = 2u]’:
    test.cpp:34:9: warning: ‘float’ is promoted to ‘double’ when passed through ‘...’ [enabled by default]
    test.cpp:34:9: note: (so you should pass ‘double’ not ‘float’ to ‘va_arg’)
    test.cpp:34:9: note: if this code is reached, the program will abort

    Könnte man durch type traits erschlagen, andererseits sind variadische Funktionen sowieso ziemlich bösartig.
    http://ideone.com/JWa9r0



  • camper schrieb:

    test.cpp: In function ‘Interpolation::Node<T, D> Interpolation::MakeNode(T, ...) [with T = float; unsigned int D = 2u]’:
    test.cpp:34:9: warning: ‘float’ is promoted to ‘double’ when passed through ‘...’ [enabled by default]
    test.cpp:34:9: note: (so you should pass ‘double’ not ‘float’ to ‘va_arg’)
    test.cpp:34:9: note: if this code is reached, the program will abort

    Könnte man durch type traits erschlagen, andererseits sind variadische Funktionen sowieso ziemlich bösartig.

    okay, das wusste ich nicht. gut zu wissen.

    naja, da mein derzeitiger compiler noch nicht c++11 kompatibel ist und da partionelle funktions-template-spezialisierungen nicht erlaubt sind, stellt sich die frage, wie ich vorgehen soll.

    kleine idee:

    template<class T>
    struct GetClass
    {
        typedef T Type;
    };
    template<>
    struct GetClass<float>
    {
        typedef double Type;
    };
    

    kann ich das so machen?


  • Mod

    referator schrieb:

    kleine idee:

    template<class T>
    struct GetClass
    {
        typedef T Type;
    };
    template<>
    struct GetClass<float>
    {
        typedef double Type;
    };
    

    kann ich das so machen?

    Sicher, löst aber das Problem nicht: Der Aufrufer übergibt (die zweite) 5 immer noch als int. Das dann einfach als double zu verwenden, wird nicht funktionieren.


Anmelden zum Antworten