Is there a way for the template function to automatically infer the type of data underlying the iterator?

I have a function where I need a data type using an iterator as the return type, for example:

#include <iostream> #include <vector> #include <iterator> template<class T, class ForwardIterator> std::vector<T> get_odd(ForwardIterator data_begin, ForwardIterator data_end) { std::vector<T> ret; std::copy_if(data_begin, data_end, std::back_inserter(ret), [](int x) { return x % 2; }); return ret; } int main() { std::vector<int> vi { 1, 2, 3, 4, 5 }; for (auto i : get_odd<int>(vi.begin(), vi.end())) std::cout << i << ", "; std::cout << std::endl; std::vector<unsigned int> vui{ 9UL, 8UL, 7UL, 6UL, 5UL }; // Note the 'char' I provided to the function, this will print weird chars for (auto i : get_odd<char>(vui.begin(), vui.end())) std::cout << i << ", "; std::cout << std::endl; return 0; } 

In main (), I have to explicitly specify the data type 'int' or 'char' of the get_odd function, is there a way to find out the data type underlying the iterator and let the template automatically subtract the correct data type?

+5
source share
4 answers

Iterator properties can be requested using std::iterator_traits :

 template<class ForwardIterator> std::vector<typename std::iterator_traits<ForwardIterator>::value_type> get_odd(ForwardIterator data_begin, ForwardIterator data_end) { std::vector<typename std::iterator_traits<ForwardIterator>::value_type> ret; std::copy_if(data_begin, data_end, std::back_inserter(ret), [](int x) { return x % 2; }); return ret; } 
+6
source

If your compiler supports C ++ 11, you can use:

 #include <type_traits> // ... typename std::remove_reference<decltype(*data_begin)>::type 

And probably a typedef for convenience:

 typedef typename std::remove_reference<decltype(*data_begin)>::type ContainedType; std::vector<ContainedType> ret; 
+2
source

It often happens that I use a convenient template alias to wrap iterator_traits :

 template <typename I> using ValueType = typename std::iterator_traits<I>::value_type; template<class ForwardIterator> std::vector<ValueType<ForwardIterator>> get_odd(ForwardIterator data_begin, ForwardIterator data_end) { std::vector<ValueType<ForwardIterator>> ret; std::copy_if(data_begin, data_end, std::back_inserter(ret), [](int x) { return x % 2; }); return ret; } 
+2
source

Use std :: iterator_traits :

 template<class ForwardIterator> std::vector<typename std::iterator_traits<ForwardIterator>::value_type> get_odd(ForwardIterator data_begin, ForwardIterator data_end) { .... } 
0
source

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


All Articles