2015-02-15 7 views
7

mir gelungen wie diese eine Klasse zu schreiben, das als nicht-statisches Attribut der Klasse definiert in einem Lambda-Erfassung:Erfassung dieses in Lambda-Attribut in einer Templat-Klasse vs nicht-Templat-Klasse

#include <memory> 
#include <iostream> 
#include <functional> 

struct S 
{ 
    S() 
    { 
    std::cout << "S::S()[" << this << "]" << std::endl; 
    } 

    std::string y_{"hi mate"}; 
    int x_; 
    std::function<void(int*)> del_{[this](int *ptr) 
    { 
    std::cout << "Deleting ptr[" << ptr << "] this[" << this << "] this->y_[" << this->y_ << "]" << std::endl; 
    }}; 
    std::unique_ptr<decltype(x_), decltype(del_)> unique_{&x_, del_}; 
}; 

int main() 
{ 
    S s; 
} 

Diese kompiliert und scheint gut zu laufen.

jedoch mit einer Templat-Klasse, ist es nicht mehr funktioniert:

#include <memory> 
#include <iostream> 
#include <functional> 

template <typename> 
struct S 
{ 
    S() 
    { 
    std::cout << "S::S()[" << this << "]" << std::endl; 
    } 

    std::string y_{"hi mate"}; 
    int x_; 
    std::function<void(int*)> del_{[this](int *ptr) 
    { 
    std::cout << "Deleting ptr[" << ptr << "] this[" << this << "] this->y_[" << this->y_ << "]" << std::endl; 
    }}; 
    std::unique_ptr<decltype(x_), decltype(del_)> unique_{&x_, del_}; 
}; 

int main() 
{ 
    S<int> s; 
} 

$> g++ -std=c++1y custom_deleter_template.cpp
~/test custom_deleter_template.cpp: In instantiation of ‘struct S::’: custom_deleter_template.cpp:9:3: required from ‘S< >::S() [with = int]’ custom_deleter_template.cpp:24:10:
required from here custom_deleter_template.cpp:15:35: internal compiler error: in tsubst_copy, at cp/pt.c:12569
std::function del_{[this](int *ptr) ^Please submit a full bug report, with preprocessed source if appropriate. See for instructions. Preprocessed source stored into /tmp/pyro/ccxfNspM.out file, please attach this to your bugreport.

Vor Einreichung einer bugreport (was ich nicht tun kann, blockiert sie die Kontoerstellung), ist es normal, dass es kompiliert nicht, basierend auf was der Standard sagt?

Compiler ist g ++ (Ubuntu 4.9.2-0ubuntu1 ~ 14.04) 4.9.2, verwendete Flag -std = C++ 1y. Gleiches passiert mit dem Flag -std = C++ 11.

+5

Interne Compilerfehler sind immer ein Fehler. Das sollte wie in [clang] (http://coliru.stacked-crooked.com/a/4e113357c1393eb6) kompiliert werden. – 0x499602D2

+0

Ich kann mit GCC 4.9.2 unter OS X reproduzieren. – Cornstalks

+0

kompiliert es in clang :). – pyro

Antwort

0

Dies ist in der Tat ein Fehler in GCC, die bereits being tracked ist.

Es scheint, 4.8 und 4.9 zu beeinflussen. Wie in den Kommentaren erwähnt, funktioniert dieses spezielle Beispiel gut für 4.7 und 5.0. Du kannst das selbst sehen here und mit den verschiedenen Versionen von gcc spielen.

Doch diese reduzierte Version des Codes ohne externe Abhängigkeit stürzt immer noch mit 5,0:

template <typename> 
struct S { 
    int f{[this](){return 42;}()}; 
}; 

int main(){ 
    return S<int>{}.f; // should return 42 
} 

Ich würde vorschlagen, dass Sie auf den Fehler warten ich, bevor Sie Ihren Code festgelegt werden referenziert, oder zu einem anderen wechseln Compiler;).

+0

Ihr Code ungültig ist, und durch Klirren abgelehnt, weil 'Lambda ' eine leere Struktur ist und hat keinen Raum für irgendwelche Daten zu speichern, einschließlich der Lambda Sie vorbei. Es wäre wahrscheinlich nützlich zu prüfen, ob ein gültiges Programm (geben Sie einfach "Lambda" einen Template-Konstruktor, der nichts tut) auf die gleiche Weise fehlschlägt. – hvd

+0

@hvd: Sie haben Recht, dass der Code schlecht formatiert ist, aber das ist neben dem Punkt, GCC sollte es auch ablehnen, nicht segfault. Dies zeigt an, dass das Frontend immer noch einige Probleme mit Lambdas in einem Vorlagenkontext hat. – Thibaut

+0

Sicher, aber es wäre ein geringeres Problem, wenn der Eis-auf-gültig ist, und nur ein Eis-auf-ungültig bleibt, als wenn es noch ein Eis-in-gültig-Problem gibt. – hvd

Verwandte Themen