2014-09-09 13 views
5

Rozważmy następujący przykład:lista Initializer jako pojemnik nie działa

#include <algorithm> 
#include <iterator> 
#include <vector> 

template<class InputIterator, class T> 
bool privIsElementOf(const T& element, InputIterator first, InputIterator last) 
{ 
    return (std::find(first, last, element) != last); 
} 

template<class Container, class T> 
bool isElementOf(const T& element, const Container & cont) 
{ 
    return privIsElementOf(element, std::begin(cont), std::end(cont)); 
} 

template<class T> 
bool isElementOf(const T& element, const std::initializer_list<T> iList) 
{ 
    return privIsElementOf(element, std::begin(iList), std::end(iList)); 
} 


int main() 
{ 
    std::vector<int> myVec { 1 , 3 , 5}; 

    bool isElement = isElementOf(3, myVec); 
    bool isElement2 = isElementOf(3, {1 , 3, 5 }); 

    return 0; 
} 

To kompiluje dobrze z drugim szablonie isElementOf z initializer_list. Niemniej jednak zawartość jest mniej więcej taka sama jak pierwszy szablon. Używa std :: begin i std :: end.

Kiedy usunąć drugi szablon, pokazuje następujący błąd kompilacji:

 

    initList.cpp: In function ‘int main()’: 
    initList.cpp:31:47: error: no matching function for call to ‘isElementOf(int,)’ 
     bool isElement2 = isElementOf(3, {1 , 3, 5 }); 
               ^
    initList.cpp:31:47: note: candidate is: 
    initList.cpp:12:6: note: template bool isElementOf(const T&, const Container&) 
    bool isElementOf(const T& element, const Container & cont) 
     ^
    initList.cpp:12:6: note: template argument deduction/substitution failed: 
    initList.cpp:31:47: note: couldn't deduce template parameter ‘Container’ 
     bool isElement2 = isElementOf(3, {1 , 3, 5 }); 
               ^

Czy ktoś może mi wyjaśnić ten problem? Szablon wymaga tylko klasy zapewniającej kompatybilność ze std :: begin i std :: end. Dlaczego szablon dla kontenera nie działa dla listy inicjalizującej? Czy istnieje sposób rozwiązania problemu za pomocą tylko jednego szablonu?

Live example

Odpowiedz

6

A function parameter for which the associated argument is an initializer list (8.5.4) but the parameter does not have std::initializer_list or reference to possibly cv-qualified std::initializer_list type

jest nie wynikają kontekst (§14.8.2.5 [temp.deduct.type]/P5), a więc nie można wywnioskować, kompilator Container. A wzmocniona lista początkowa sama w sobie nie ma typu.

Jedną z możliwości jest zapewnienie domyślny szablon argumentu na pokrycie tej sprawy:

template<class T, class Container = std::initializer_list<T>> 
bool isElementOf(const T& element, const Container & cont) 
{ 
    return privIsElementOf(element, std::begin(cont), std::end(cont)); 
} 

pamiętać, że nie należy używać initializer_list domyślny argument, chyba że jesteś pewien, że kod nie będzie mieć wpływu na jego semantyka kopiowania - na żywotność podstawowej tablicy nie ma wpływu żadne kopiowanie obiektu initializer_list.

Powiązane problemy