SFINAE z nieprawidłowymi parametrami typu function czy array?
Proszę wziąć pod uwagę ten kod:
template<typename T>
char (&f(T[1]))[1];
template<typename T>
char (&f(...))[2];
int main() { char c[sizeof(f<void()>(0)) == 2]; }
Spodziewałam się, że zrobi SFINAE i wybierze drugie przeciążenie, ponieważ Zamiana T
na T[1]
daje
void [1]()
Który jest nieprawidłowym typem, oczywiście. Dostosowanie typów parametrów (array - >pointer) odbywa się po zamianie parametrów szablonu na parametry funkcji i sprawdzeniu poprawnych typów wynikowych, takich jak 14.8.2 [temp.odliczenie] opisuje.
Ale zarówno comeau, jak i GCC nie kompilują powyższego. Zarówno z różnymi diagnostyka.
Comeau mówi:
"Chodź.c", linia 2: Błąd: tablica funkcji jest niedozwolona
char (&f(T[1]))[1];
GCC mówi (wersja 4.3.3
):
Błąd: ISO C++ zabrania tablicy o rozmiarze zerowym
c
Oznacza, że GCC nie może zastąpić, ale wybiera pierwsze przeciążenie f
, zwracając sizeof
z 1, zamiast nie zastępować go z przodu, jak Comeau.
Jaki kompilator ma rację i czy mój kod jest w ogóle poprawny? Proszę zapoznać się z odpowiednią częścią standardową lub zacytować ją w odpowiedzi. Dzięki!
Update : Sam Standard zawiera taki przykład na liście w 14.8.2/2
. Nie wiem dlaczego pierwszy to przeoczyłem:
template <class T> int f(T[5]);
int I = f<int>(0);
int j = f<void>(0); // invalid array
Chociaż przykład ma jedynie charakter informacyjny, pokazuje intencję wszystkich tych tajemniczych akapitów i wydaje się, że powyższy kod powinien działać i odrzucić pierwsze przeciążenie.
3 answers
Mała notka, choć bardzo rzadka, znalazłem kilka okazji, w których wierzyć, że kompilator Comeau się myli - chociaż te okazje są tak rzadkie, że zawsze warto podwójnie i potrójnie sprawdzam twoje założenia!
Mogę mieć powód do zachowania g++. Nie jestem pewien, czy to podany dokładnie, gdy typy parametrów są dostosowywane:
Rozważ, co następuje:
template<typename T>
struct A
{
void bar (T[10]);
};
template<typename T>
void A<T>::bar (T*)
{
}
Definicja " bar "jest legalna, ponieważ" T[10] "rozpada się na"T*". Tak. nie widzę nic w standard, który zabrania kompilatorowi wykonanie korekt określonych w pkt 8.3.5 w odniesieniu do deklaracji wzorcowej, poprawia również wydajność, jeśli chodzi o dopasowanie przeciążenia.
Stosując to do twojego przykładu, g++ może traktować to jako:
template<typename T>
char (&f( T* ))[1];
template<typename T>
char (&f(...))[2];
int main() { char c[sizeof(f<void()>(0)) == 2]; }
W powyższym parametrze podstawiony jest prawnym wskaźnikiem do funkcji, a nie tablicy funkcji.
Więc, pytanie dla mnie jest - czy jest coś, co zabrania korekty dla funkcji parametry (8.3.5) dwa razy?
[[3]} osobiście uważam, że to ma sens, aby umożliwić dostosowanie się do dwa razy, bo inaczej komplikuje dopasowanie szablonu funkcji przeciążeniaPodsumowując, myślę, że to poprawne dla g++, aby wybrać pierwsze przeciążenie opierając się na tym, jak traktuje rozkładające się parametry tablicy, a Comeau jest błędne nie mieć błędu dedukcyjnego dla tablicy funkcji.
Oczywiście teraz oznacza to, że (jeśli Comeau został naprawiony) wtedy każdy kompilator wybierze różne przeciążenia i nadal będzie standardy posłuszny! :(
EDIT:
Aby zilustrować mój punkt widzenia, rozważ następujący kod:
template <typename T> void foo ( T * );
template <typename T> void foo ( T * const );
template <typename T> void foo ( T [] );
template <typename T> void foo ( T [10] );
template <typename T> void foo ( T [100] );
void bar ()
{
foo < void() > ( 0 );
}
Tutaj foo zostało zadeklarowane i ponownie zgłoszone kilka razy. Która deklaracja, a więc jaki typ parametru, powinien stosować reguły wymienione w 14.8.2?
Chodzi mi o to, że standard nic nie mówi o powyższym. Posunąłbym się również do stwierdzenia, że każde sformułowanie w tej sprawie musiałoby zostawić jest to zachowanie" undefined "lub" implementation defined".
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-21 17:44:15
Zaskakujące-to działa w VS2008. Nie sądzę, że to koniecznie dowód na to, że jest to poprawne zachowanie,czy nie...
Visual Studio interpretuje
char (&f(T[1]))[1];
Jako funkcja, która pobiera tablicę o rozmiarze 1 T i zwraca odwołanie do tablicy znaków o rozmiarze 1.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-04 21:36:53
Postaram się opisać proces dedukcji argumentu szablonu, jak rozumiem to z lektury standardu.
- jawne argumenty szablonu są sprawdzane zgodnie z opisem w 14.8.2 / 2.
- wynikowa sygnatura funkcji jest dostosowywana zgodnie z 8.3.5 (tzn. wykonywana jest zanik tablicy do wskaźnika).
- domyślne argumenty szablonu są wyprowadzane zgodnie z pkt 14.8.2.1 (odbywa się to na częściowo podstawionym podpisie z etapu 2).
Odliczenie za pierwsze przeciążenie nie powiedzie się w kroku 1, dlatego rozdzielczość przeciążenia zwraca drugie przeciążenie. Nie wierzę, że program jest źle uformowany.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-04 22:02:10