2016-10-07 24 views
8

P0091R3 ("Template argument deduction for class templates") został niedawno dodany do gcc trunk i może być testowany na wandbox.Czy "dedukowanie argumentu szablonu" w C++ 17 dla szablonów klas pozwala wnioskować o typach lokalnych?

Coś miałem na myśli była możliwość wykorzystania go do realizacji „strażnika Zakres” w niewielu linii kodu:

scope_guard _([]{ cout << "hi!\n" }); 

próbowałem implementing it on wandbox ...

template <typename TF> 
struct scope_guard : TF 
{ 
    scope_guard(TF f) : TF{f} { } 
    ~scope_guard() { (*this)(); } 
}; 

int main() 
{ 
    scope_guard _{[]{}}; 
} 

... ale kompilacja nie powiodła się z następującym błędem:

prog.cc:6:5: error: 'scope_guard(TF)-> scope_guard<TF> [with TF = main()::<lambda()>]', declared using local type 'main()::<lambda()>', is used but never defined [-fpermissive] 
    scope_guard(TF f) : TF{std::move(f)} { } 
    ^~~~~~~~~~~ 

Następnie próbowałem using a non-lambda local type i dostał ten sam błąd.

int main() 
{ 
    struct K { void operator()() {} }; 
    scope_guard _{K{}}; 
} 

Następnie I tried a non-local type, i to działało jak oczekiwano.

struct K { void operator()() {} }; 

int main() 
{ 
    scope_guard _{K{}}; 
} 

Czy to featured zaprojektowane w taki sposób, że uniemożliwia lokalne typy przed wywnioskować?

Lub jest to defekt w aktualnej implementacji funkcji gcc?

+1

Wygląda na to, że już znalazłeś i skomentowałeś raport o błędzie. – Barry

Odpowiedz

7

Jest to błąd w obecnej realizacji: 77890 ( NEW oznacza ważność, w przeciwieństwie do niepotwierdzone ustalonej 7,0). Będąc w stanie wydedukować lambda była jedną z motywacji przykłady oryginalnego papieru, więc byłoby dość niewygodne jeśli to nie działa:

// Virtually impossible to pass a lambda to a template class' constructor without declaring the lambda 
for_each(vi2.begin(), vi2.end(), Foo<???>([&](int i) { ...})); 
for_each(vi.begin(), vi.end(), Foo([&](int i) { ...})); // Now easy instead of virtually impossible 

możemy stworzyć naprawdę podstawowy przykład:

template <typename TF> 
struct scope_guard 
{ 
    scope_guard(TF) { } 
}; 

int main() 
{ 
    scope_guard _([]{}); 
} 

należy wykonać rozdzielczości przeciążenia syntetyzowany zestawu funkcji obejmującej funkcje:

template <class TF> scope_guard<TF> synthesized(TF); 
template <class TF> scope_guard<TF> synthesized(scope_guard<TF> const&); 
template <class TF> scope_guard<TF> synthesized(scope_guard<TF>&&); 

, która powinna wybrać pierwsze przeciążenie i użyć tego zwracanego typu jako typu _, z TF będącym typem lambda. To wszystko powinno działać.

+0

[Oryginał jest teraz kompilowany na ** wandbox **] (http://melpon.org/wandbox/permlink/DOEBWFOU6YyKLPYe). –