I have a function where I need an iterator's underlying data type as return type, like this:
#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 the main(), I have to explicitly provide data type 'int' or 'char' to the get_odd function, is there a way to find out iterator's underlying data type, and let template automatically deduct the correct data type?
A code for template function is generated when the function is instantiated. The functions are often instantiated when they are first time called (in the code), but there are other ways to instantiate a function - do a so-called 'explicit instantiation'.
Function templates are similar to class templates but define a family of functions. With function templates, you can specify a set of functions that are based on the same code but act on different types or classes.
A function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.
Which one is suitable syntax for function template? Explanation: Both class and typename keywords can be used alternatively for specifying a generic type in a template.
Iterator properties can be queried 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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With