Zastanawiam się, czy możliwe jest rozszerzenie podejścia SFINAE na wykrywanie, czy dana klasa ma pewną funkcję członka (jak omówiono tutaj:Jak ustalić, czy dana klasa ma określoną funkcję na szablonie?
"Czy istnieje technika w C++, aby wiedzieć, czy klasa ma funkcję członka z podpisem? " Check if a class has a member function of a given signature
) w celu obsługi szablonowych funkcji składowych? Na przykład. aby być w stanie wykryć funkcji foo w poniższej klasy:
struct some_class {
template < int _n > void foo() { }
};
I że może to być możliwe, aby to zrobić dla danej instancji foo (np sprawdzić, czy void foo<5>()
jest członkiem) w następujący sposób:
template < typename _class, int _n >
class foo_int_checker {
template < typename _t, void (_t::*)() >
struct sfinae { };
template < typename _t >
static big
test(sfinae< _t, &_t::foo<_n> > *);
template < typename _t >
static small
test(...);
public:
enum { value = sizeof(test<_class>(0)) == sizeof(big) };
};
Następnie zrobić foo_int_checker< some_class, 5 >::value
sprawdzić czy some_class
ma człon void foo<5>()
. Jednak na MSVC++ 2008 to zawsze zwraca false
natomiast g ++ daje następujące błędy składniowe w wierszu test(sfinae< _t, &_t::foo<_n> >);
test.cpp:24: error: missing `>' to terminate the template argument list
test.cpp:24: error: template argument 2 is invalid
test.cpp:24: error: expected unqualified-id before '<' token
test.cpp:24: error: expected `,' or `...' before '<' token
test.cpp:24: error: ISO C++ forbids declaration of `parameter' with no type
Oba wydają się niepowodzeniem, ponieważ staram się uzyskać adresu konkretyzacji funkcji szablon z typem, który sam parametr szablonu. Czy ktoś wie, czy jest to możliwe, czy z jakiegoś powodu jest zabronione przez standard?
EDYCJA: Wygląda na to, że pominięto składnię ::template
, aby uzyskać g ++, aby poprawnie skompilować powyższy kod. Jeśli zmienię bit, w którym otrzymam adres funkcji na &_t::template foo<_n>
, program kompiluje, ale otrzymuję to samo zachowanie, co MSVC++ (value
jest zawsze ustawione na false
).
Gdybym zakomentuj ...
przeciążenie test
aby zmusić kompilator, aby wybrać drugi, pojawia się następujący błąd kompilatora g ++ w:
test.cpp: In instantiation of `foo_int_checker<A, 5>':
test.cpp:40: instantiated from here
test.cpp:32: error: invalid use of undefined type `class foo_int_checker<A, 5>'
test.cpp:17: error: declaration of `class foo_int_checker<A, 5>'
test.cpp:32: error: enumerator value for `value' not integer constant
gdzie linia 32 jest linia enum { value = sizeof(test<_class>(0)) == sizeof(big) };
. Niestety, to nie wydaje mi pomóc zdiagnozować problem :(MSVC++ daje podobny błąd nieokreślony..
error C2770: invalid explicit template argument(s) for 'clarity::meta::big checker<_checked_type>::test(checker<_checked_type>::sfinae<_t,&_t::template foo<5>> *)'
na tej samej linii
Co dziwne jest to, że jeśli dostanę adres ze specyficznym klasy, a nie parametr szablonu (tj. raczej niż &_t::template foo<_n>
I do &some_class::template foo<_n>
), a następnie otrzymuję prawidłowy wynik, ale wtedy moja klasa kontrolera jest ograniczona do sprawdzania pojedynczej klasy (some_class
) dla funkcji. Ponadto, jeśli zrobię co następuje:
template < typename _t, void (_t::*_f)() >
void
f0() { }
template < typename _t >
void
f1() {
f0< _t, &_t::template foo<5> >();
}
i zadzwoń pod numer f1<some_class>()
, a następnie NIE otrzymuję błędu kompilacji na &_t::template foo<5>
. Sugeruje to, że problem powstaje tylko podczas pobierania adresu funkcji szablonu z typu, który sam jest parametrem szablonu, podczas gdy w kontekście SFINAE. Argh!
C++ wysłano za 5 lat: D Zobacz http://stackoverflow.com/questions/36780867/i-neet-to-know-at-compilation-time-if-class-a-has- a-funkcja-członek-na-b/36780868 # 36780868 –