The list of initializers as a container does not work

Consider the following example:

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

It compiles well with the second isElementOf template with the initializer_list parameter. However, the content more or less matches the content of the first template. It uses std :: begin and std :: end.

When I delete the second template, it shows the following compilation error:

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

Can someone explain the problem to me? The template simply asks for a class that provides compatibility with std :: begin and std :: end. Why does the template for the container not work for the initialization list? Is there a way to solve the problem with only one template?

Living example

+5
source share
1 answer

Function parameter, for which the associated argument is the list of initializers (8.5.4), but the parameter does not have std::initializer_list or a link to a possible qualification cv std::initializer_list type

- non-output context (ยง14.8.2.5 [temp.deduct.type] / p5), therefore the compiler cannot output the Container . The bit-init list itself has no type.

One possibility is to provide a default template argument to cover this case:

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

Please note that you should not use the default initializer_list argument if you are not sure that its copy semantics will not be affected by the code - the copying of the initializer_list object does not affect the lifetime of the base array.

+6
source

Source: https://habr.com/ru/post/1202126/


All Articles