anio
anio

Reputation: 9161

Can I easily make a template function that takes an arbitrary container of an arbitrary type and operates on it?

I'm trying to get something like this to work:

// This method is wrong, won't work, need your help
template < template <typename T> class U >
void foo(U& u) 
{
  T& blah = *u.begin();
}

int main(int, char**)
{
  vector<int> myVec(4, 10);
  foo<vector<int> >(myVec); // This is how I want to call it, even better if I can leave the parameters out and just do foo(myVec);
  return EXIT_SUCCESS;
}

Really what I want to do is avoid the following because it seems redundant:

template <typename T, typename U>
void foo(U& u)
{
T& blah = *u.begin(); 
}

int main(int, char**)
{
  vector<int> myVec(4, 10);
  foo<int, std::vector<int> >(myVec); // first int in parameters is redundant cause I already provide int as arg to vector
  return EXIT_SUCCESS;
}

Upvotes: 3

Views: 215

Answers (5)

Omnifarious
Omnifarious

Reputation: 56038

If you need this to work for container-like types that do not follow STL conventions regarding a value_type typedef then you need a tagging system. Here is an example of how you would make this work.

template <typename U>
struct foo_tags {
   typedef typename U::value_type value_type;
};

template <typename U>
void foo(U& u)
{
    typedef foo_tags<U>::value_type T;
    T& blah = *u.begin(); 
}

class my_very_special_int_container {
 public:
   int *begin();
};

template <>
struct foo_tags<my_very_special_int_container>
{
    typedef int value_type;
}

int main(int, char**)
{
  vector<int> myVec(4, 10);
  foo(myVec);
  my_very_special_int_container c;
  foo(c);
  return EXIT_SUCCESS;
}

Upvotes: 2

Stuart Golodetz
Stuart Golodetz

Reputation: 20616

Try this:

#include <vector>

template <template <typename, typename> class Cont, typename T, typename Alloc>
void foo(Cont<T,Alloc>& cont)
{
    T& blah = *cont.begin();
}

int main(int, char**)
{
    std::vector<int> myVec(4, 10);
    foo(myVec);
    return EXIT_SUCCESS;
}

What's wrong with your original version is that vector has an additional template parameter (the allocator type). Also, you need to specify the template parameters, as I'm doing above.

All of this being said, I think I prefer Oli and FreakEnum's version, as it's more generic! :)

Upvotes: 5

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272467

You can just do:

template <typename U>
void foo(U& u)
{
    typedef typename U::value_type T;
    T& blah = *u.begin(); 
}

int main(int, char**)
{
  vector<int> myVec(4, 10);
  foo(myVec);
  return EXIT_SUCCESS;
}

Upvotes: 8

Mr.Anubis
Mr.Anubis

Reputation: 5312

you can do :

template < typename U>
void foo(U& u) 
{
  typename U::value_type blah = *u.begin();
}

Upvotes: 6

Michael Krelin - hacker
Michael Krelin - hacker

Reputation: 143051

Use std::vector<int>::reference type? Is that what you're asking for?

Upvotes: 1

Related Questions