2014-09-09 21 views
5

consideri seguente esempio:Initializer lista come contenitore non funziona

#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; 
} 

compila bene con il secondo modello isElementOf con l'initializer_list. Tuttavia il contenuto più o meno lo stesso del primo modello. Utilizza std :: begin e std :: end.

Quando rimuovo il secondo modello, mostra seguente errore di compilazione:

 

    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 }); 
               ^

Qualcuno mi può spiegare il problema? Il modello richiede solo una classe che fornisce compatibilità con std :: begin e std :: end. Perché il modello per contenitore non funziona per l'elenco di inizializzatori? C'è un modo per risolvere il problema con un solo modello?

Live example

risposta

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

è un contesto non dedotta (§14.8.2.5 [temp.deduct.type]/P5), in modo che il compilatore non può dedurre Container. A contraced-init-list di per sé non ha tipo.

Una possibilità è quella di fornire un argomento modello predefinito per coprire questo caso:

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)); 
} 

Notare che non è necessario utilizzare un argomento initializer_list di default se non si è sicuri che il codice non sarà influenzato dal suo copia della semantica - la durata dell'array sottostante non è influenzata da alcuna copia dell'oggetto initializer_list.

Problemi correlati