2017-06-03 9 views
13

Mam więc funkcję z określoną sygnaturą w pliku nagłówkowym i chcę zadeklarować inną funkcję z dokładnie tą samą sygnaturą w klasie bez wpisania na klawiaturze parametry znowu i oczywiście, miejmy nadzieję, bez makra ... Funkcja elementu powinna mieć oczywiście dodatkowy ukryty parametr, wskaźnik this (ponieważ nie jest on statyczną funkcją składową).Użycie decltype do zadeklarowania całego typu funkcji (nie wskaźnika!)

Teraz jestem zaskoczony, że następujący hack/trick działa zarówno w GCC, jak i ICC, ale nie jestem pewien, czy jest to "legalne" C++. Nie jestem szczególnie zainteresowany legalnością , jeśli jest to obsługiwane rozszerzenie, ale niestety nie chcę, aby łamało się aktualizacja wersji kompilatora, ponieważ niektórzy ludzie zdecydowali się na arbitralnie blokować tej użytecznej funkcji, ponieważ standard mówi "nie" (tego rodzaju rzeczy naprawdę mnie denerwują, jeśli mam być szczery).

Oto co mam na myśli:

// test.hpp 
int func(int x) { return x; } 

struct foo 
{ 
    decltype(func) fn; // <-- legal? 
}; 

int test() 
{ 
    return foo().fn(6); 
} 


// then in test.cpp 
int foo::fn(int x) { return x + 42; } 

Ten prace (GCC i ICC), ale nie wiem, czy jest to "legalne" w standardzie. Proszę o zapewnienie, że jest to legalne i nie przestanie nagle działać w przyszłości.

(jeśli nie jest to zgodne z prawem i chcesz zgłosić to jako błąd, prosimy oznaczyć go jako sugestię, aby to legalne przedłużenie kompilator zamiast zabić go ...)

Zasadniczo, jest to taka sama jak deklarowanie int fn(int x); w strukturze i tak to działa obecnie.

Jeśli pytasz mnie o przypadek użycia: jest to deklaracja funkcji elementu otoki dla innej wolnej funkcji, która robi coś ze wskaźnikiem this przed przekazaniem go do funkcji bezpłatnej. Jego parametry muszą oczywiście dokładnie pasować. Ponownie, nie chcę ponownie wpisywać parametrów.

+3

Jest to zgodne z prawem, o ile nie jest to typ zależny w szablonie klasy. –

+1

W celu dodatkowego nadużycia można "zainicjować" go za pomocą "= 0;" i uczynić go wirtualnym –

+0

@ JohannesSchaub-litb Ciekawe i nie na temat, ale ciekawy: co robi inicjowanie go z 0 zrobić? Wiem tylko, że możesz "zainicjować" to za pomocą = delete. – kktsuri

Odpowiedz

4

To wygląda legalnie; ale z definicji musisz ponownie wpisać. Zastanów się zamiast tego, używając doskonałego przekazywania.

+0

Masz rację, ale w jaki sposób mogę użyć idealnego przekazywania, jeśli jest zdefiniowane w innej jednostce tłumaczeniowej (pliku cpp)? Mam na myśli, że mogę uczynić go "szablonem zewnętrznym" (lub po prostu pozostawić to niezdefiniowanym) w pliku nagłówkowym (deklaracja), ale czy tworzenie wystąpień nie będzie stanowić problemu? Czy możesz podać przykład, bez konieczności wpisywania go (dobrze, oczywiście, ponowne wpisywanie bezpłatnej funkcji 'func' jest w porządku, oczywiście). Może po prostu przegapię coś prostego. – kktsuri

+0

W każdym razie, przyjmuję twoją odpowiedź, ponieważ odpowiada na pytanie, ale byłoby miło wiedzieć o perfekcyjnym przekazywaniu z inną jednostką tłumaczeniową (rzeczywiste funkcje mają bardziej skomplikowane operacje i chcę je zachować w jednym miejscu, ponieważ kompiluję z LTO będą i tak kierowani nawet przez jednostki tłumaczeniowe). Dzięki – kktsuri

+0

Dziwne jest to, że typ 'fn' i' func' to nie to samo 'static_assert (std :: is_same {}," ") ; 'Widzę, jak to działałoby legalnie, jak OP ma, ale może również wyobrazić sobie, że' decltype' nie jest tu dozwolony, ponieważ 'fn' nie jest typu' int (int) ' –

Powiązane problemy