Oto ten sam kod z niektórymi leksykalnym zaciemniania wyjęte:
1043 template <typename Tp, typename Up>
1044 class is_assignable_helper
1046 {
1047 template <typename Tp1, typename Up1>
1048 static decltype(declval<Tp1>() = declval<Up1>(), one())
1049 test(int);
1050
1051 template<typename, typename>
1052 static two test(...);
1053
1054 public:
1055 static constexpr bool value = sizeof(test<Tp, Up>(0)) == 1;
1056 };
Klasa ta używa SFINAE zrobić brudną robotę. Oznacza to, że wartość zmiennej value
zależy od wybranej funkcji test()
w oparciu o rozdzielczość przeciążenia. Jedno przeciążenie przyjmuje liczbę całkowitą, a drugie przyjmuje argument C variadic (określony przez elipsę). Jeśli wystąpi , przy pierwszym przeciążeniu, zostanie wybrane drugie przeciążenie.
Jeśli wystąpi błąd zastąpienia , pojawi się, będzie pochodzić z wyrażenia declval<Tp1>() = declval<Up1>()
. declval<T>()
to deklaracja funkcji, która "zwraca" wartość typu std::add_rvalue_reference<T>::type
. Ta funkcja jest używana głównie w nienazwanych kontekstach, takich jak decltype()
, sizeof()
, noexcept()
itp., Aby uzyskać instancję typu bez jawnego wywoływania konstruktora (ponieważ ten typ może nie mieć dostępnego konstruktora). Jeśli chcesz się dowiedzieć, dlaczego jest to wybrany typ zwrotu, zobacz this post.
Po uzyskaniu wystąpienia typu można wywoływać funkcje członkowskie/nie-członkowskie w tych instancjach. Używaną funkcją składową jest operator=()
. Jeśli klasa nie ma operatora przypisania (lub ma niedostępną), nastąpi awaria zastępowania. Zamiast tego zostanie wybrana wersja zastępcza (variadic) test()
.
Powodem różnicy w rodzaju argument (int
vs ...
) dlatego ...
ma najniższy stopień konwersji i działa jako „ostatniej szansy” dla rozdzielczości przeciążenia. Nie możemy po prostu zostawić parametrów pustych, bo otrzymamy błąd redeclaracji.
jak dla typu powrotnego test
- w przypadku awarii podstawienie nie nie występuje (wartość typu Up
mogą być przypisane do wartości typu Tp
), a następnie powraca test()
typu zakończonych powodzeniem. Jeśli wystąpi błąd zastąpienia, wybierana jest wersja awaryjna zwracająca błąd wskazujący typ. Te typy są zróżnicowane poprzez sprawdzenie ich rozmiarów. Czekamy na sukces porównując z 1
.
Zobacz: http://en.cppreference.com/w/cpp/types/is_assignable – Brandon
Nie jestem pewien, co masz na myśli przez "przewidywanie typu obiektu". Rodzaje są określone za pomocą parametrów szablonu. – 0x499602D2
tak, ale jak by się dowiedzieć, czy typ można przypisać do innego typu? – Kam