G++4.8: internal compiler error: Segmentation fault (program cc1plus)



  • camper schrieb:

    Schritt 0: den exakten Quelltext posten.

    Klick

    alterbernd schrieb:

    Schritt 1: Aktuelle GCC-Version aus dem VCS[...]

    Nun... Ich hab noch nie was von der Abkürzung "VCS" gehört, könntest Du vielleicht noch schnell erläutern was das ist?

    einself schrieb:

    Leider ist LWS[...]

    Ich habs echt nicht so mit Abkürzungen 😃



  • Eine Abwandlung bringt bei mir sogar clang (3.2) zum Absturz. Während gcc (4.3.6, 4.4.7, 4.5.4, 4.6.3) ebenfalls mit ICE aussteigen, beschweren sich gcc 4.7.2 und 4.8.0 über Überschreitung der Instantiierungstiefe. Da könnte sogar etwas dran sein.

    template <bool, typename = void> struct enable_if {};
    template <typename T> struct enable_if<true,T> { typedef T type; };
    
    struct A {};
    
    template<typename T, typename = A&>
    struct trait
    { static const bool value = false; };
    
    template<typename T>
    struct trait<T, decltype(fun( (A()), (T()) ))>
    { static const bool value = true; };
    
    struct foo
    {
        foo() {}
        template<typename T>
        foo(const T&, typename enable_if<trait<T>::value>::type* =0)
        {}
    };
    
    A& fun(A, foo);
    A& fun(A, int);
    
    int main()
    {
        int x;
        foo y(x);
    }
    


  • Es scheint, als ob die Instantiierung des Templatekonstruktors (genauer: der Deklaration) eine Copy/Move umfasst - und obwohl nat. die üblichen Copy/Move-Konstruktoren zur Verfügung stehen, führt das zu rekursiver Instantiierung. Denn der Konstruktor ist zwar kein Copy-ctor, aber trtzdem einer, der zum Kopieren eines Objektes geeignet wäre. Wenn ich einen Dummyparamtere hinzufüge

    template <bool, typename = void> struct enable_if {};
    template <typename T> struct enable_if<true,T> { typedef T type; };
    
    struct A {};
    
    template<typename T, typename = A&>
    struct trait
    { static const bool value = false; };
    
    template<typename T>
    struct trait<T, decltype(fun( (A()), (T()) ))>
    { static const bool value = true; };
    
    struct foo
    {
        foo() {}
        template<typename T>
        foo(int, const T&, typename enable_if<trait<T>::value>::type* =0)
        {}
    };
    
    A& fun(A, foo);
    A& fun(A, int);
    
    int main()
    {
        int x;
        foo y(0,x);
    }
    

    gibt es keine Probleme mit irgendeinem der Compiler, die ich getest habe. Das scheint auch mit gnihihihihi s Code zu funktionieren. Schön ist das nat. nicht.



  • Tatsache! 😃
    Mit dem Dummyparameter läufts wie geschmiert, Danke für die Info.

    "Gelöst" habe ich das nun so:

    class title{
    ...
    
        template<typename TitleType, typename LineType,
                  typename = typename std::enable_if<is_printable<TitleType>::value && is_printable<LineType>::value>::type>
        title(char, const TitleType& title_name, const LineType& title_line)
            : name(nothrow_cast<std::string>(title_name)), line(nothrow_cast<std::string>(title_line)) {}
    
    public:
    
    ...
    
        template<typename TitleType, typename LineType = std::string>
        title(const TitleType& title_name, const LineType& title_line = LineType()) : title(0, title_name, title_line) {}
    ...
    };
    


  • Damit wird die Überladung aber nicht mehr ohne Fehler entfernt. Wenn das so sein soll, wäre static_assert mit einer passend Fehlermeldung sinnvoller.



  • camper schrieb:

    Damit wird die Überladung aber nicht mehr ohne Fehler entfernt. Wenn das so sein soll, wäre static_assert mit einer passend Fehlermeldung sinnvoller.

    Uhm...
    Stimmt, ich verstehe aber grad nicht warum.

    Dann benutze ich eben vorerst einen static_assert .



  • Nun, so gehts auch:

    template<typename TitleType, typename LineType = std::string>
                title(const TitleType& title_name, const LineType& title_line = LineType()){
                    set_name(title_name);
                    set_line(title_line);
                }
    

    wegen:

    template<typename Type, typename = typename std::enable_if<is_printable<Type>::value>::type>
                void set_name(const Type& title_name){
                    name = nothrow_cast<std::string>(title_name);
                }
    
                template<typename Type, typename = typename std::enable_if<is_printable<Type>::value>::type>
                void set_line(const Type& title_line){
                    line = nothrow_cast<std::string>(title_line);
                }
    

    Aber der lässt dennoch jeden Typ durch - ob printable oder nicht o__O

    Folgendes kompiliert bei mir einwandfrei:

    int main(){
        class X {} x;
        fast::io::title t(x); // oder fast::io::title().set_name(x);
        return 0;
    }
    

    Sollte es aber nicht.

    Mit static_assert habe ich es auch schon versucht, der lässt ebenfalls jeden Typen durch.

    Das hab ich so benutzt:

    static_assert(is_printable<TitleType>::value && is_printable<LineType>::value, "hier die fehlermeldung");
    

    Was mach ich denn nun schon wieder falsch? o__O
    Und vor allem wo ist der Kopf-Gegen-Die-Wand-Smiley?

    Grüße...



  • Eine simple (und korrekte) Lösung dürfte darin bestehen, is_printable extra zu spezialisieren für Klassen, die is_printable in ihren Konstruktoren verwenden.



  • camper schrieb:

    Eine simple (und korrekte) Lösung dürfte darin bestehen, is_printable extra zu spezialisieren für Klassen, die is_printable in ihren Konstruktoren verwenden.

    Ich denke nicht, dass ich jetzt das fabriziert habe, was Du vorgeschlagen hast, aber wenn ich folgendes schreibe:

    template<typename T>
    class is_printable_constructor : public is_printable<Type> {};
    

    und schlussendlich

    template<typename TitleType, typename LineType = std::string,
              typename = typename std::enable_if<is_printable_constructor<TitleType>::value && is_printable_constructor<LineType>::value>::type>
    title(const TitleType& title_name, const LineType& title_line = LineType())
        : ... {}
    

    gibts kein Compiler-Segfault mehr.
    Funktionieren tuts ja nun zumindest, aber ist die Lösung auch "zulässig" oder einfach nur Mist?

    Grüße.



  • Der Spuck findet kein Ende.

    Nachdem ich nun die set_default() Methode von meiner Menü-Klasse implementieren wollte, kamen komische redefinition errors - ratet mal von welcher Klasse.
    is_printable<>


    Schlussendlich habe ich nun sowas gebaut:

    template<typename Type, typename = std::ostream&>
    class is_printable_impl : public std::false_type {};
    
    template<typename Type>
    class is_printable_impl<Type, decltype(std::declval<std::ostream&>() << std::declval<Type>())> : public std::true_type {};
    
    template<typename Type>
    class is_printable : public is_printable_impl<Type> {};
    

    Wobei die Klasse is_printable nun sowohl im Konstruktor als auch sonst wo endlich wie gewünscht funktioniert.
    manmanman...


Anmelden zum Antworten