views:

71

answers:

2

Hi, the following code is an example of something I'm trying to do in a large project:

#include <iostream>
#include <vector>

// standard template typedef workaround
template<typename T> struct myvar {typedef std::vector<T> Type;};

template<typename T>
T max(typename myvar<T>::Type& x)
// T max(std::vector<T>& x)
{
  T y;
  y=*x.begin();
  for( typename myvar<T>::Type::iterator it=x.begin(); it!=x.end(); ++it )
    if( *it>y ) 
      y=*it;
  return y;
} 

int main(int argc, char **argv)
{
  myvar<int>::Type var(3);
  var[0]=3;
  var[1]=2;
  var[2]=4;
  std::cout << max(var) << std::endl;
  return 0; 
} 

When I try to compile it I get:

>g++ delme.cpp -o delme
delme.cpp: In function ‘int main(int, char**)’:
delme.cpp:25: error: no matching function for call to ‘max(std::vector<int, std::allocator<int> >&)’

However, if I comment out line 8 and uncomment line 9 it compiles properly and gives:

>g++ delme.cpp -o delme
>./delme 
4

Can someone please explain why the function template definition of max() using typename myvar<T>::Type& isn't considered as a match for ‘max(std::vector<int, std::allocator<int> >&)’ and is there a way to get it to match without using the underlying std::vector<T>& type?

+1  A: 

Instead of coding this yourself have you considered using std::max_element instead? It takes a begin and end iterator and I believe does what you want here.

Mark B
Thanks, but I was just using `max()` as an example. I have other functions where the same problem occurs. I will keep `std::max_element` in mind for next time I want a maximum though... :-)
Brett Ryland
+5  A: 

Deducing the enclosing type (or any attributes of the enclosing type) from its the nested type is impossible. It is one of the examples of so called non-deduced context in C++.

While the template function declaration itself is legal, you won't be able to call your function as mere max(var) since the template argument deduction cannot be carried out. In your case, the compiler will not be able to figure out that parameter x of type std::vector<int> implies that T is myvar<int>.

You'll always have to specify template arguments for max explicitly, as in

std::cout << max<int>(var) << std::endl;

How to work around this problem depends on what you were trying to achieve by introducing that enclosing myvar template.

AndreyT
I see, thanks.The reason for the `myvar` template is to use column_major matrices in ublas without requiring the user to always specify this, i.e.,namespace Cheb{ template<typename T> struct matrix { typedef boost::numeric::ublas::matrix<T,boost::numeric::ublas::column_major> type; };}I then want my functions to have arguments of type `Cheb::matrix<T>::type`. I don't have too many templated functions, so I can survive with specifying my template arguments explicitly, but it'd be nice to not have to.
Brett Ryland