2014-09-29 14 views
5

Oto implementacja std::is_assignable, Spędziłem kilka godzin próbując uzyskać, w jaki sposób statycznie wykombinować typ obiektu szablonowego, ale nie mógł.Jak działa std :: is_assignable?

W standardzie is_assignable stwierdza się, że obie strony przypisania są przekształcane na std::add_rvalue_reference<T>::type. Nie dostaję tego zdania ani nie widzę, w jaki sposób można użyć std::add_rvalue_reference<T>::type do przewidywania typu obiektu.

Czy ktoś mógłby podać mi proste wyjaśnienie, które mogę wykorzystać jako pierwszy krok do zrozumienia, w jaki sposób działa std :: is_assignable?

+0

Zobacz: http://en.cppreference.com/w/cpp/types/is_assignable – Brandon

+0

Nie jestem pewien, co masz na myśli przez "przewidywanie typu obiektu". Rodzaje są określone za pomocą parametrów szablonu. – 0x499602D2

+0

tak, ale jak by się dowiedzieć, czy typ można przypisać do innego typu? – Kam

Odpowiedz

6

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.

+0

'==' nie jest operatorem przypisania. – Oktalist

+0

@Oktalist Dzięki.:) – 0x499602D2

+0

* "w celu uzyskania instancji typu bez jawnego wywoływania konstruktora" * lub destruktora. - 'operator =()' potrzebuje parametru – dyp