2015-06-26 10 views
9

Rozważmy następujący kod:Zrozumienie szablon odliczenie argumentem

#include <vector> 

template <typename T> 
using v_itt = typename std::vector<T>::iterator; 

template <typename T> 
void foo(v_itt<T>){ } 

int main() { 
    typename std::vector<long>::iterator i = std::vector<long>().begin(); 
    foo(i); //candidate template ignored: couldn't infer template argument 'T' 
} 

DEMO

Co jest nie tak z kodem? Myślałem, że T należy wydedukować na long. Czy jest jakiś sposób, aby to naprawić?

Odpowiedz

5
typename std::vector<T>::iterator 

iterator (rodzaj zależny) jest nie wywnioskować w kodzie, ponieważ jest w zagnieżdżonych nazwa specyfikatorem a średnia mówi

§14.8.2.5/4

Jednak w niektórych kontekstach wartość nie bierze udziału w odliczaniu typów, ale zamiast tego używa wartości argumentów szablonu, które zostały albo wydedukowane gdzie indziej, albo wyraźnie określone. Jeśli parametr szablonu jest używany tylko w kontekstach niewynikających i nie jest jawnie określony, odliczanie argumentu szablonu kończy się niepowodzeniem.

i §14.8.2.5/5

niepoddanej wywnioskować konteksty są:

- zagnieżdżona nazwa-specyfikator typu, który został określony za pomocą kwalifikowanej ID.

więc nie jest to wydedukowany kontekst.

Możliwe obejścia:

  1. Przepuścić odniesienie wektor zamiast iteratora
  2. Zastosowanie znaczników dyspozytorskich oraz compile time assertions aby zweryfikować swoją iterator
3

Chciałbym tylko dodać ewentualnego obejścia 3 do odpowiedzi Marco:

#include <vector> 

template<typename T> 
void real_foo(typename std::vector<T>::iterator){} 

template <typename T> 
void foo(T i){ real_foo<typename decltype(i)::value_type>(i); } 

int main() { 
    std::vector<long> v; 
    foo(v.begin()); 
} 
+2

Dobre rozwiązanie: jeszcze mniej gadatliwe. Dzięki, Paolo. –

+0

Dobra sztuczka, tak. Dziękuję Ci. –

+2

@MarcoA. Cóż, nie jest to zbyt eleganckie, ponieważ polega tylko na awarii czasu kompilacji, nie dostarczając użytkownikowi żadnych wiadomości, ale jest to po prostu inny sposób robienia tego samego :) –