template error with iterator

U

utab

Dear all,

I was experimenting with a template taking two iterators for the range
of
a vector.(Perhaps, it is sth simple and I am missing it because it is
a
late hour.) I ran into problems in the compile phase , the code is
below:

#include <iostream>
#include <algorithm>
#include <stdexcept>
#include <vector>

using std::domain_error;
using std::sort;
using std::vector;

template <class T, class Ran>
T median(Ran b, Ran e)
{
typedef typename vector<T>::size_type vec_sz;

vec_sz size = (e-b)/sizeof(T);
if (size == 0)
throw domain_error("median of an empty vector");

sort(b, e);

vec_sz mid = size/2;

return size % 2 == 0 ? (b[mid] + b[mid-1]) / 2 : b[mid];
}

int main()
{
vector<double> vec;
for(int i=0;i!=10;++i)
vec.push_back(i);
std::cout << median(vec.begin(), vec.end()) << std::endl;
return 0;
}


I get

83.cc: In function 'int main()':
83.cc:38: error: no matching function for call to
'median(__gnu_cxx::__normal_iterator<double*, std::vector<double,
std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*,
std::vector<double, std::allocator<double> > >)'

I am supplying the median function with iterators by using the begin
and
end member functions of the vector. However, I get a type mismatch
error
on iterators I guess. Could you clarify the problem for me?

Rgds,
 
U

utab

Dear all,

I was experimenting with a template taking two iterators for the range
of
a vector.(Perhaps, it is sth simple and I am missing it because it is
a
late hour.) I ran into problems in the compile phase , the code is
below:

#include <iostream>
#include <algorithm>
#include <stdexcept>
#include <vector>

using std::domain_error;
using std::sort;
using std::vector;

template <class T, class Ran>
T median(Ran b, Ran e)
{
typedef typename vector<T>::size_type vec_sz;

vec_sz size = (e-b)/sizeof(T);
if (size == 0)
throw domain_error("median of an empty vector");

sort(b, e);

vec_sz mid = size/2;

return size % 2 == 0 ? (b[mid] + b[mid-1]) / 2 : b[mid];

}

int main()
{
vector<double> vec;
for(int i=0;i!=10;++i)
vec.push_back(i);
std::cout << median(vec.begin(), vec.end()) << std::endl;
return 0;

}

I get

83.cc: In function 'int main()':
83.cc:38: error: no matching function for call to
'median(__gnu_cxx::__normal_iterator<double*, std::vector<double,
std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*,
std::vector<double, std::allocator<double> > >)'

I am supplying the median function with iterators by using the begin
and
end member functions of the vector. However, I get a type mismatch
error
on iterators I guess. Could you clarify the problem for me?

Rgds,

Forgot to tell that I use g++ 4.1.2
 
T

tragomaskhalos

template <class T, class Ran>
T median(Ran b, Ran e)
{
  typedef typename vector<T>::size_type vec_sz;

  vec_sz size = (e-b)/sizeof(T);
  if (size == 0)
    throw domain_error("median of an empty vector");

  sort(b, e);

  vec_sz mid = size/2;

  return size % 2 == 0 ? (b[mid] + b[mid-1]) / 2 : b[mid];

}

int main()
{
  vector<double> vec;
  for(int i=0;i!=10;++i)
    vec.push_back(i);
  std::cout << median(vec.begin(), vec.end()) << std::endl;

The compiler cannot deduce T; replace the above call with
 
U

utab

template <class T, class Ran>
T median(Ran b, Ran e)
{
typedef typename vector<T>::size_type vec_sz;
vec_sz size = (e-b)/sizeof(T);
if (size == 0)
throw domain_error("median of an empty vector");
sort(b, e);
vec_sz mid = size/2;
return size % 2 == 0 ? (b[mid] + b[mid-1]) / 2 : b[mid];

int main()
{
vector<double> vec;
for(int i=0;i!=10;++i)
vec.push_back(i);
std::cout << median(vec.begin(), vec.end()) << std::endl;

The compiler cannot deduce T; replace the above call with
return 0;

Thanks, I read something similar in the faq as well.
 
A

acehreli

template <class T, class Ran>
T median(Ran b, Ran e)
{

According to that definition, there is no relation between T and Ran.

[...]
std::cout << median(vec.begin(), vec.end()) << std::endl;

The complier cannot deduce T for that call because the return values
are never a part of function signatures. You can try specifying it
yourself:

median<double>(vec.begin(), vec.end());

Ali
 
G

Greg Herlihy

I was experimenting with a template taking two iterators for the range
of
a vector.(Perhaps, it is sth simple and I am missing it because it is
a
late hour.) I ran into problems in the compile phase , the code is
below:

#include <iostream>
#include <algorithm>
#include <stdexcept>
#include <vector>

using std::domain_error;
using std::sort;
using std::vector;

template <class T, class Ran>
T median(Ran b, Ran e)
{
  typedef typename vector<T>::size_type vec_sz;

  vec_sz size = (e-b)/sizeof(T);
  if (size == 0)
    throw domain_error("median of an empty vector");

  sort(b, e);

  vec_sz mid = size/2;

  return size % 2 == 0 ? (b[mid] + b[mid-1]) / 2 : b[mid];
}

The C++ compiler is not able to deduce the type "T" from the median()
function call. Since "T" is dependent on the iterator type "Ran", I
would eliminate "T" altogether. Note also that the calculation of
"size" is incorrect - e-b will return the number of positions between
two random access iterators.

Applying these suggestions produces a program like this one:

#include <iostream>
#include <algorithm>
#include <stdexcept>
#include <vector>
#include <iterator>

using std::domain_error;
using std::sort;
using std::vector;

template <class Ran>
typename std::iterator_traits<Ran>::value_type
median(Ran b, Ran e)
{
size_t size = e-b;
if (size == 0)
throw domain_error("median of an empty vector");
sort(b, e);
size_t mid = size/2;
return size % 2 == 0 ? (b[mid] + b[mid-1]) / 2 : b[mid];
}

int main()
{
vector<double> vec;

for (int i=0; i!=10; ++i)
vec.push_back(i);

std::cout << median(vec.begin(), vec.end()) << std::endl;
return 0;
}

Greg
 
J

James Kanze

[...]
.. or throw away the redundant template parameter:
template <class Ran>
typename Ran::value_type median(Ran b, Ran e)

There's no guarantee that Ran has a typedef for value_type (and
there have definitely been implementations of the standard
library where it didn't for std::vector<>).

This should be:

template< typename RandomAccessIterator >
{
typedef typename vector<Ran::value_type>::size_type vec_sz;

And here, even worse, since you're tying yourself to
std::vector. (Even as it stands, you need an additional
typename in the template argument.) Also, the difference
between to random access iterators is a difference_type, not a
size_type. So it should be:

vec_sz size = (e-b)/sizeof(Ran::value_type);

And of course, you don't want the division.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,061
Latest member
KetonaraKeto

Latest Threads

Top