I have the following piece of code:
//code.h
#include<string>
#include<iterator>
#include<iostream>
using std::string;
using std::advance;
using std::iterator;
using std::cin;
using std::cout;
using std::endl;
bool chk_if_uniq (string);
bool per_scan(iterator,iterator);
//code.cpp
#ifndef CODE_H
#define CODE_H
#include "code.h"
#endif
int main (){
string input_string;
cout << "enter string: ";
cin >> input_string;
auto result = chk_if_uniq(input_string);
if(result){
cout << input_string << " contains unique characters." << endl;
}
else{
cout << input_string << " contains non-unique characters." << endl;
}
return 0;
}
bool chk_if_uniq (string s){
auto bIter = s.begin();
auto eIter = s.end();
bool iterPos = (bIter != eIter);
auto flag = true;
while(iterPos){
flag = per_scan(bIter,eIter);
if(!flag){
break;
}
advance(bIter,1);
}
return flag;
}
bool per_scan(iterator it, iterator eIter){
auto nxIt = it;
bool iterPos = (nxIt != eIter);
auto flag = true;
do{
++nxIt;
if(iterPos){
if(*nxIt == *it){
flag = false;
}
}
}while(flag);
return flag;
}
I have the following compilation command:
g++ -ggdb -g3 -o -pedantic-errors -std=c++17 -Wall -Wextra -Wpedantic
The version of gcc that I am using is 8.4.1.
I get the following compiler errors:
In file included from code.cpp:3:
code.h:13:15: error: ‘auto’ parameter not permitted in this context
bool per_scan(iterator,iterator);
^~~~~~~~
code.h:13:24: error: ‘auto’ parameter not permitted in this context
bool per_scan(iterator,iterator);
^~~~~~~~
code.cpp: In function ‘bool chk_if_uniq(std::__cxx11::string)’:
code.cpp:33:31: error: too many arguments to function ‘bool per_scan()’
flag = per_scan(bIter,eIter);
^
In file included from code.cpp:3:
code.h:13:6: note: declared here
bool per_scan(iterator,iterator);
^~~~~~~~
code.cpp: At global scope:
code.cpp:43:24: error: ‘auto’ parameter not permitted in this context
bool per_scan(iterator it, iterator eIter){
^~
code.cpp:43:37: error: ‘auto’ parameter not permitted in this context
bool per_scan(iterator it, iterator eIter){
^~~~~
code.cpp: In function ‘bool per_scan()’:
code.cpp:45:15: error: ‘it’ was not declared in this scope
auto nxIt = it;
^~
code.cpp:45:15: note: suggested alternative: ‘int’
auto nxIt = it;
^~
int
code.cpp:46:27: error: ‘eIter’ was not declared in this scope
bool iterPos = (nxIt != eIter);
^~~~~
code.cpp:46:27: note: suggested alternative: ‘extern’
bool iterPos = (nxIt != eIter);
^~~~~
extern
As is evident from the error log, all the errors emanate from the usage of iterator
as a parameter type for the method per_scan
in the header file.
Obviously, my understanding of the iterator concept is flawed.
Can someone point out what is wrong with the usage?
TIA
Yes your understanding is flawed. Your usage of the std::iterator
template reminds of generics in Java, that are placeholders for the concrete types. They are based on type erasure. Templates on the other hand can be used for type erasure but they don't do it out of the box. A class template must be instantiated before it can be used. The parameter type of a function is a type, not a template. This
bool per_scan(std::iterator,std::iterator);
Makes no sense because std::iterator
is not a type.
Moreover, std::iterator
is meant to be used as helper when implementing custom iterators. Using an instantiation of std::iterator
as function parmeter is rarely useful, as it restricts the parameter type to instantiations of the std::iterator
template, but not all iterators fit that. Actually I am not aware of any iterator in the standard library that is an instantiation of std::iterator
. One advantage of iterators is that most of the time you do not need to care about the concrete type. For example std::vector::iterator
can be implemented as pointer. You need not care.
Consider how eg standard algorithms are declared. The type of the iterators is usually a template argument that makes no assumptions about implementation details (cf eg std::find
). The requirements on the implementation are defined in named requirements or via concepts (since C++20). See https://en.cppreference.com/w/cpp/named_req/Iterator.
Change the function into a function template:
template <typename Iter>
bool per_scan(Iter it, Iter eIter){
auto nxIt = it;
bool iterPos = (nxIt != eIter);
auto flag = true;
do{
++nxIt;
if(iterPos){
if(*nxIt == *it){
flag = false;
}
}
}while(flag);
return flag;
}