2015-02-15 14 views
7

sono riuscito a scrivere una classe come questa, catturando questo in un lambda definito come attributo non-statico di detta classe:Capture questo attributo lambda all'interno di una classe su modelli vs classe non-template

#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; 
} 

Questo compila e sembra funzionare bene.

Tuttavia, con una classe template, che non funziona più:

#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.

Prima di presentare una bugreport (che non posso fare, hanno bloccato la creazione di account), è normale che non si compila, in base a ciò che dice lo standard?

Il compilatore è g ++ (Ubuntu 4.9.2-0ubuntu1 ~ 14.04) 4.9.2, utilizzato flag -std = C++ 1y. La stessa cosa accade con flag -std = C++ 11.

+5

Gli errori interni del compilatore sono sempre un bug. Questo dovrebbe essere compilato come fa in [clang] (http://coliru.stacked-crooked.com/a/4e113357c1393eb6). – 0x499602D2

+0

Posso riprodurre con GCC 4.9.2 su OS X. – Cornstalks

+0

compila in clang :). – pyro

risposta

0

Questo è in effetti un bug in GCC, che è già being tracked.

Sembra interessare 4.8 e 4.9. Come sottolineato nei commenti, questo particolare esempio funziona bene per 4.7 e 5.0. Puoi vederlo da solo here e giocare con le diverse versioni di gcc.

Tuttavia questa versione ridotta del codice senza dipendenza esterna si blocca ancora con 5.0:

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

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

vorrei suggerire di attendere il bug ho fatto riferimento da fissare prima di utilizzare il codice, o passare a un altro compilatore;).

+0

Il tuo codice non è valido e viene respinto da clang perché 'Lambda ' è una struttura vuota e non ha spazio per la memorizzazione di nulla, incluso il lambda che stai passando. Sarebbe probabilmente utile verificare se un programma valido (basta dare a 'Lambda' un costruttore basato su modelli che non fa nulla) fallisce allo stesso modo. – hvd

+0

@hvd: Hai ragione sul fatto che il codice sia formattato male, ma questo è oltre il punto, GCC dovrebbe anche rifiutarlo, non segfault. Questo indica che il frontend ha ancora alcuni problemi relativi a lambda in un contesto di template. – Thibaut

+0

Certo, ma sarebbe un problema minore se il ghiaccio su valido è stato risolto, e rimane solo un ghiaccio non valido, che se c'è ancora un problema valido per il ghiaccio. – hvd