Receive iterators as arguments and know class - c++

I need to create a method that receives iterators as arguments and return a templated collection of the same type.
I created a minimal example the demonstrates my need:
#include <list>
#include <iostream>
using namespace std;
class A {
int i;
public:
A(int _i) : i(_i) {}
operator int() {
return i;
}
};
class B {
int i;
public:
B(int _i) : i(_i) {}
operator int() {
return i;
}
};
template <class T>
list<T> method(typename list<T>::iterator begin, typename list<T>::iterator end) {
list<T> res; // I need the template class here
for (; begin != end; begin++) {
cout << *begin; // Whatever...
}
return res;
}
int main() {
list<A> listA = {1, 2, 3};
list<B> listB = {4, 5, 6};
auto res1 = method(listA.begin(), listA.end()); // Cannot change
auto res2 = method(listB.begin(), listB.end()); // Cannot change
}
This is not a working example, but I am looking for a way to make this work.
The important part is the method and it's arguments, and that it will return a templated class with T. So I can change the method as much as i want but the auto res1 = method(listA.begin(), listA.end()); should stay the same. (not my code)
How can I do something like this?

In this particular case (if you know that it's std::list) you can get value_type from iterator itself:
template <class T>
auto method(T begin, T end) {
list<typename T::value_type> res; // I need the template class here
for (; begin != end; begin++) {
cout << *begin; // Whatever...
}
return res;
}
value_type = U only for std::list<U>

typename list<T>::iterator is a non-deduced context. You need to either pass the container itself or specify it as an explicit template argument.

Iterators designate a sequence; they do not have to be associated with a "collection". For example, you can create an iterator that reads input from the console.
If you want to restrict a function to only work with containers, then write it that way:
template <class T>
T f(const T& container) {
// whatever; code that uses begin() and end()?
}

This isn't possible. You can have iterators that don't correspond to any container. The function that calls method should create an empty list and pass a back_inserter to the list as the third argument to method. Use std:copy as an example of what your method should look like.

Related

C++ Template Function to Iterate Over any Collection Member Field

I am attempting to write a template function that iterates over a user-specified field within some collection of structs. For example, I want to write the following C++:
struct Example {
int a;
bool b;
};
template<std::function<Field& (Class)> GetField, typename Field, typename Class>
void myFunc(std::iterator<Class> begin, size_t const length) {
cout << length << endl;
for (size_t i{ 0 }; i < length; ++begin, ++i) {
Field const &field{ GetField(*begin) };
// Forward field to some other template function
anotherTemplateFunction<Field>(field);
}
}
void main() {
Example exArray[]{ {5, true}, {8, false} };
std::list<Example> exList{ exArray, exArray + _countof(exArray) }
// Examples of how I would like to call myFunc...
myFunc<Example::a>(exArray, _countof(exArray));
myFunc<Example::b>(exList.begin(), exList.size());
}
The above doesn't work, but hopefully the intent is clear. How can I write the myFunc template method to accomplish generic iteration over some field of each iterated item? Alternatively, if there is some way (in Boost or the Standard Library) to directly create an iterator over exArray[i].a, that would also be acceptable.
What I usually use is something like:
void main() {
std::array<Example, 2> exArray{ {5, true}, {8, false} };
std::list<Example> exList{ exArray.begin(), exArray.end() };
auto access_a = [](Example& e)->int&{ return e.a;};
auto access_b = [](Example& e)->bool&{ return e.b;};
myFunc(exArray.begin(), exArray.end(), access_a);
myFunc(exList.begin(), exList.end(), access_b);
}
template<class ForwardIt, class Accessor>
void myFunc(ForwardIt begin,ForwardIt end, Accessor accessor) {
cout << end - begin << endl;
for (auto it = begin; it != end; it++) {
// Forward field to some other template function
anotherTemplateFunction(accessor(*it));
}
}
Please notice how I used std::array instead of a raw c style array.
If you have access to a c++11 compiler, std::array (or std::vector) should always be preferred over raw c arrays. ES.27
In order to need less boilerplate code, consider using some serialization libraries which solve this "iterating over class fields" problem, for example boost serialization or magic get.
It's simple if you know the pointer to member syntax and the likes. Unfortunately is so rarely used, is kind of an esoteric feature of the language:
template <class T> void foo(T);
template <auto Field, class It>
auto myFunc(It begin, It end)
{
for (; begin != end; ++begin)
{
foo((*begin).*Field);
}
}
int main()
{
std::vector<Example> v{{5, true}, {8, false}};
myFunc<&Example::a>(v.begin(), v.end()); // will call foo<int>(5) , foo<int>(8)
myFunc<&Example::b>(v.begin(), v.end()); // will call foo<bool>(true) , foo<bool>(false)
}
For the template <auto Field you need C++17.
For C++11 the syntax is more verbose:
template <class T, class F, F T::* Field, class It>
void myFunc(It begin, It end)
{ /* same */ }
int main()
{
std::vector<Example> v{{5, true}, {8, false}};
myFunc<Example, int, &Example::a>(v.begin(), v.end()); // will call foo<int>(5) , foo<int>(8)
myFunc<Example, bool, &Example::b>(v.begin(), v.end()); // will call foo<bool>(true) , foo<bool>(false)
}
A little bit OT to your question, but I don't understand why you complicate yourself with that initialization of std::list. In C++ your first container of choice should be std::vector.
Also there is no std::iterator

Global Function Parameter

I am building a stack using arrays (no std::vector allowed) and I must implement a global method that serves as a constructor. The input parameters are two iterators (begin and end) and I have to create a stack from those. The problem is that before i actually create the stack i have to check whether or not is empty. Since I can not pass the stack as a parameter, how am I supposed to call methods on that?
Here is my code:
template <typename IterT>
void method(IterT begin, IterT end) {
try {
if(!is_empty())
make_empty();
for(; begin!=end; ++begin) {
push(static_cast<T>(*begin));
}
}
catch(...) {
clear();
throw;
}
}
Obviously is not working, the methods is_empty(), make_empty(), push() and clear() needs something to work on.
My test method is:
int a[5] = {7, 2, 33, 4, 1111};
stack<int> sp;
sp.push(25); //check if stack is made empty
sp.print();
sp.method(a, a+5);
sp.print();
If it has to be global method that serves as a constructor then what you can do is:
inside stack.h class insert friend declaration for this global method like:
template <typename T>
class stack {
template <typename U, typename IterIt>
friend stack<U> construct(IterIt beg, IterIt end);
private:
T* inside_;
};
In stack.cpp we can now define this construct method:
#include "stack.h"
#include <cstddef>
template <typename T, typename IterIt>
stack<T> construct(IterIt beg, IterIt end) {
// warning: works only with iterators defining binary operator-
stack<T> result;
size_t elems = end - beg;
result.inside_ = new T[elems];
T* add_to = result.inside_;
while (beg != end) {
*add_to = *beg;
++add_to;
++beg;
}
return result;
}
And with simple main method you can have:
int main() {
int a[] = {1,2,3,4,5};
stack<int> s = construct<int>(a, a + 5);
}
I hope this solves your problem. Remember, there might be some corner cases that you would need to solve, but as a baseline I think this should suffice.

generic iterators to access elements of vectors without using Templates c++

I am creating a function which should take as input iterators to vector
for example:
vector<int> a;
foo(a.begin(),a.end())
The vector can hold any type.
Now the simple way to do this is using templates
template <typename Iterator>
void foo(Iterator first, Iterator last) {
for (Iterator it = first; it!=last; ++it) {
cout << *it;
}
}
I want to know if there is a way to achieve the same functionality without using templates. Since using Templates would force me to include these functions in Header file of a public API which I don't want to. So I wanted to know is there an alternate way to access the iterators without using Templates.
There are ways not to include the implementation in header files but they are not clean to implement (for instance you should know in advance the instantiations). Read here for more info about this issue:
Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?
How can I avoid linker errors with my template functions?
For instance in:
foo.h
#ifndef HI_
#define HI_
template<class Iterator>
void foo(Iterator first, Iterator last);
#endif
foo.cpp
#include "stack.h"
using namespace std;
template<class Iterator>
void foo(Iterator first, Iterator last) {
for (Iterator it = first; it != last; ++it) {
cout << *it << " ";
}
}
template
void foo( std::vector<int>::iterator first, std::vector<int>::iterator last);
template
void foo( std::vector<double>::iterator first, std::vector<double>::iterator last);
Now you can use foo function only for double and int. Other types won't link.
Hope this helps.
This is a long answer. The short answer is "type erasure"; go learn about it.
The long answer is two answers. First I cover "do you just want to be able to iterate over contiguous ints?". Then you want span. This is a really simple form of type erasure that forgets what the exact container is you are working on so long as it is contiguous and over T.
The second answer is if you actually need to deal with multiple types (not just int) and multiple kinds of containers (not just contiguous ones).
The two answers are separated by a line.
The span concept (see gsl::span) is designed for pretty much this reason. It itself is a template (over the type you are working with), but it will be a concrete instance of a template in most interfaces.
Here is a toy version of it:
template<class T>
struct span_t {
T* b = 0;
T* e = 0;
T* begin() const { return b; }
T* end() const { return e; }
span_t(span_t const&)=default;
span_t& operator=(span_t const&)=default;
span_t()=default;
span_t( T* s, T* f ):b(s),e(f) {}
span_t( T* s, std::size_t l):span_t(s, s+l){}
template<std::size_t N>
span_t( T(&arr)[N] ):span_t(arr, N) {}
std::size_t size() const { return end()-begin(); }
bool empty() const { return begin()==end(); }
T& front() const { return *begin(); }
T& back() const { return *(std::prev(end()); }
T* data() const { return begin(); }
span_t without_front( std::size_t N=1 ) const {
return {std::next( begin(), (std::min)(N, size()) ), end()};
}
span_t without_back( std::size_t N=1 ) const {
return {begin(), std::prev(end(), (std::min)(N, size()) )};
}
};
we can augment it with conversion operators
namespace details {
template<template<class...>class Z, class, class...Ts>
struct can_apply:std::false_type{};
template<class...>using void_t=void;
template<template<class...>class Z, class...Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z,void,Ts...>;
template<class C>
using dot_data_r = decltype( std::declval<C>().data() );
template<class C>
using dot_size_r = decltype( std::declval<C>().size() );
template<class C>
using can_dot_data = can_apply< dot_data_r, C >;
template<class C>
using can_dot_size = can_apply< dot_size_r, C >;
can_dot_data detects via SFINAE if .data() is valid to do on an object of type C.
Now we add a constructor:
template<class T,
std::enable_if_t<
can_dot_data<T&>{}
&& can_dot_size<T&>{}
&& !std::is_same<std::decay_t<T>, span_t>{}
, int
> =0
>
span_t( T&& t ): span_t( t.data(), t.size() ) {}
which covers std::vector and std::string and std::array.
Your function now looks like:
void foo(span_t<int> s) {
for (auto&& e:s)
std::cout << s;
}
}
with use:
std::vector<int> a;
foo(a);
now, this only works for contiguous containers of a specific type.
Suppose this is not what you want. Maybe you do need to solve this for a myriad of types, and you don't want to expose everything in the header.
Then what you need to do is known as type erasure.
You need to work out what minimal set of operations you need from the provided types. Then you need to write wrappers that "type erase" these operations down to "typeless" operations.
This goes in the header, or in another helper header.
In the interface of the function, or in a header intermediate helper, you take the incoming types and do the type erasure, then pass the type-erased types into the "real" implementation.
An example of type erasure is std::function. It takes almost anything that can be invoked with a fixed signature, and turns it into a single type-erased type. Everything except how to copy, destroy and invoke an instance of the type is "forgotten" or erased.
For your case:
template <typename Iterator>
void foo(Iterator first, Iterator last) {
for (Iterator it = first; it!=last; ++it) {
cout << *it;
}
}
I see two things that need to be erased down to; iteration, and printing.
struct printable_view_t {
void const* data = 0;
void(*print_f)(std::ostream& os, void const*) = 0;
explicit operator bool()const{return data;}
printable_view_t() = default;
printable_view_t(printable_view_t const&) = default;
template<class T,
std::enable_if_t<!std::is_same<T, printable_view_t>{}, int> =0
>
printable_view_t( T const& t ):
data( std::addressof(t) ),
print_f([](std::ostream& os, void const* pv){
auto* pt = static_cast<T const*>(pv);
os << *pt;
})
{}
std::ostream& operator()(std::ostream& os)const {
print_f(os, data);
return os;
}
friend std::ostream& operator<<(std::ostream& os, printable_view_t p) {
return p(os);
}
};
printable_view_t is an example of type-erasing "I can be printed".
void bar( printable_view_t p ) {
std::cout << p;
}
void test_bar() {
bar(7);
bar(3.14);
bar(std::string("hello world"));
}
The next thing we'd have to do is type erase iteration. This is harder, because we want to type erase iteration over iterating over a printable_view_t type.
Type erasing foreach is a tad easier, and often more efficient.
template<class View>
struct foreach_view_t {
void* data = 0;
void(*func)( std::function<void(View)>, void* ) = 0;
explicit operator bool()const{return data;}
foreach_view_t() = default;
foreach_view_t(foreach_view_t const&) = default;
template<class T,
std::enable_if_t<!std::is_same<std::decay_t<T>, foreach_view_t>{}, int> =0
>
foreach_view_t( T&& t ):
data( const_cast<std::decay_t<T>*>(std::addressof(t)) ),
func([](std::function<void(View)> f, void* pv){
auto* pt = static_cast<std::remove_reference_t<T>*>(pv);
for (auto&& e : *pt)
f(decltype(e)(e));
})
{}
void operator()(std::function<void(View)> f)const{
func(f, data);
}
};
we then daisy chain these together
void foo(foreach_view_t<printable_view_t> x) {
x([](auto p){ std::cout << p; });
}
test code:
std::vector<int> a{1,2,3};
foo(a);
Now much of the header code was "hoisted" into the type erasure types instead of a function template body. But careful choice of the points of type erasure can let you keep what you need from the types precise and narrow, and the logic of how you use those operations private.
As an example, the above code doesn't care where you are printing it to; std::cout was not part of the type erasure.
Live example.
I want to know if there is a way to achieve the same functionality without using templates. [...] I wanted to know is there an alternate way to access the iterators without using Templates.
Yes, if you use C++14, but...
Since using Templates would force me to include these functions in Header file of a public API which I don't want to.
... isn't a useful way for you because it's equivalent to use templates and you have to put it in the header file.
In C++14 you can use a lambda function with auto parameters.
auto foo = [](auto first, auto last)
{ for (auto it = first ; it != last; ++it ) std::cout << *it; };
The autos aren't template (from a formal point of view) but are equivalent and you can't declare foo in the header and develop it in a cpp file.

In C++11 is there a way to not require template arguments when calling a function that takes any callable as an argument, including bound methods?

In order to broaden my understanding of C++11, I'm experimenting with writing functional helpers and seeing if I can make calling them less verbose. Consider the following code:
#include <list>
int timesTwo(int x) { return x*2; }
int timesX(int x, int y) { return x*y; }
class Foo {
public:
Foo(int a) : value(a) {};
int fooTimesTwo() const { return value*2; };
int value;
};
template <class T, class U>
std::list<U> myMap(const std::list<T> &list, const std::function<U(const T &)> &func)
{
std::list<U> result;
for(typename std::list<T>::const_iterator it = list.begin(); it != list.end(); ++it) {
result.push_back(func(*it));
}
return result;
}
int main()
{
std::list<int> numbers = {1,2,3,4,5};
std::list<int> numbers2 = myMap<int,int>(numbers, [] (int x) { return x*2; });
std::list<int> numbers3 = myMap<int,int>(numbers, &timesTwo);
std::list<int> numbers4 = myMap<int,int>(numbers, std::bind(timesX, 2, std::placeholders::_1));
std::list<Foo> fooList = {Foo(1), Foo(2), Foo(3), Foo(4)};
std::list<int> numbers5 = myMap<Foo,int>(fooList, &Foo::fooTimesTwo);
return 0;
}
Is there anyway to rewrite myMap so that
all four of the calls to it in my code example do not require any template arguments, and...
there's only one general implementation, and I don't have to manually write an overloaded version for each combination of types I want to call it with?
I've tried changing the second argument of myMap to be a third templated type instead of std::function, but it fails because a) the second templated type U can't be inferred, and b) even if it could, the fourth call to myMap will cause an error on line 20 due to &Foo::fooTimesTwo not being a function or function pointer.
I'm willing to consider all of the various features of C++11 to do this, and I don't particularly care if it makes the declaration or definition of myMap obtuse or unreadable. I'm just wondering if it's possible and, if so, what sort of techniques and C++11 features can accomplish it.
You could attempt to implement std::invoke in C++11, but I think it would be really cumbersome.
It's fairly simple to make a function template for a generalized callable:
template <class T, class F>
auto myMap(const std::list<T> &list, F&& func)
-> std::list<typename std::decay<decltype(func(*list.begin()))>::type>
{
using U = typename std::decay<decltype(func(*list.begin()))>::type;
std::list<U> result;
for(typename std::list<T>::const_iterator it = list.begin(); it != list.end(); ++it) {
result.push_back(func(*it));
}
return result;
}
You get expression sfinae for free. Now there's only member function pointer to be taken care of:
template <class T, class F>
auto myMap(const std::list<T> &list, F&& func)
-> std::list<typename std::decay<decltype(((*list.begin()).*func)())>::type>
{
return myMap(list, [=](T const& t){ return (t.*func)(); });
}
Now you can call your functions as expected. demo
While at it, you could replace this ugly for loop with a ranged for:
for(auto const& elem : list) {
results.push_back(func(elem));
}
Or use an algorithm:
std::transform(list.begin(), list.end(), std::back_inserter(result), func);

Return template iterator based on argument class

I'm writing an algorithm function that uses iterators. This function should work with both normal and constant iterators, and importantly the class that these iterators come from is NOT a template, I know it in advance.
Is there any way to enforce in the following definition that the iterators come from a specific class?
// This is an example, A could be any other class with exposed iterators.
using A = std::vector<int>;
// How to enforce that Iterator is an iterator from A?
template <typename Iterator>
Iterator foo(Iterator begin, Iterator end);
...
A a;
auto it = foo(a.begin(), a.end());
*it = 4; // Must compile
// --------
const A a;
auto it = foo(a.begin(), a.end());
*it = 4; // Must not compile
// --------
B b;
auto it = foo(b.begin(), b.end()); // Should not compile.
In this case, foo does not modify directly the supplied range, but allows for modification of the result iterator if the supplied range was modifiable in the first place. It would be nice if this could be done without replicating code.
Simply don't use template:
A::iterator foo(A::iterator begin, A::iterator end);
You might use std::enable_if:
#include <type_traits>
#include <vector>
class X : public std::vector<int> {};
class Y : public std::vector<double> {};
template <typename Iterator>
typename std::enable_if<std::is_same<Iterator, X::iterator>()
|| std::is_same<Iterator, X::const_iterator>(),
Iterator>::type
foo(Iterator begin, Iterator end) {
return begin;
}
int main() {
X x0;
auto i0 = foo(x0.begin(), x0.end());
*i0 = 4; // Must compile
const X x1;
auto i1 = foo(x1.begin(), x1.end());
// error: assignment of read-only location
//*i1 = 4; // Must not compile
Y y;
// error: no type named ‘type’ in ‘struct std::enable_if ...
//auto i2 = foo(y.begin(), y.end()); // Should not compile
}
Or static_assert as a nicer alternative:
template <typename Iterator>
Iterator foo(Iterator begin, Iterator end) {
static_assert(std::is_same<Iterator, X::iterator>()
|| std::is_same<Iterator, X::const_iterator>(),
"No X::iteator or X::const_iterator");
return begin;
}
You could use a function overload check:
inline void check_must_be_iterator_from_A(A::iterator) {}
inline void check_must_be_iterator_from_A(A::const_iterator) {}
template <typename I>
I foo(I a, I b) {
typedef void (*must_be_iterator_from_A)(I);
must_be_iterator_from_A c = &check_must_be_iterator_from_A;
//...
}
The other option is to use template specialization to create a constraint, which makes the code within the function terser and definitely without runtime penalty regardless of compiler:
template <typename I> struct is_iterator_from_A;
template <> struct is_iterator_from_A<A::iterator>{ enum {ok}; };
template <> struct is_iterator_from_A<A::const_iterator>{ enum {ok}; };
template <typename I>
I bar(I a, I b) {
is_iterator_from_A<I>::ok;
return a;
}
I would first write your function for const iterators and then write a wrapper around it for the non_const case:
A::const_iterator foo(A::const_iterator start, A::const_iterator end) {
std::cout << " Called foo with const iterators " << std::endl;
return start;
}
A::iterator foo(A::iterator start, A::iterator end) {
std::cout << " Called foo with non_const iterators " << std::endl;
auto it = foo(static_cast<A::const_iterator>(start), static_cast<A::const_iterator>(end));
return start + std::distance(static_cast<A::const_iterator>(start), it);
}
If you inline the wrapper function you should get zero (or nearly zero) overhead.
EDIT:
In case your container doesn't provide random access iterators distance has linear complexity and you will have to use std::advance instead of the "+"-operator, so depending on your performance requirements this might not be a viable solution for you.