In C++11/C++14,
template <
   typename T ,
   template <typename...> class Container_t
>
void MyFunc(Container_t<T> &data) { ... }
template <typename T>
void MyFunc2( T v ) { ... }
int main()
{
   std::vector<char> v;
   MyFunc<char, std::vector>(v);     // OK
   MyFunc(v);                        // error
   int i;
   MyFunc2<int>(i);                  // OK
   MyFunc2(i);                       // OK
}
I get an error with MyFunc(v).  
Is it possible in any way to let the compiler find out the type of the container passed to the variadic template function? I can see no problems in finding it out, as with a normal types in normal templates.
If I need to change the type of v, do I have to fix all the calls to MyFunc?
Compiler: Microsoft Visual C++ 2015 (v140)
Instead of trying to deduce container type, assume container defines what type it stores.
template <typename Container>
void MyFunc(Container& data)
{ 
   // all std containers defines value_type member (also reference etc.)
   using std::begin;
   using value_type = typename Container::value_type;
   value_type value = *begin(data);
  ...
}
Please note, that you might not need type of stored elements at all:
template <typename Container>
void MyFunc(Container& data)
{ 
   using std::begin;
   auto value = *begin(data);
  ...
}
if you want to work on std containers only (or the ones with similar templates arguments) - see Richard Hodges answer.
The trick is to name the template's template arguments:
#include <vector>
#include <iostream>
#include <typeinfo>
template <
   typename T ,
   typename A,
   template <typename = T, typename = A> class Container_t
>
void MyFunc(Container_t<T, A> &data) { 
     std::cout << "value type = " << typeid(T).name() << std::endl;
     std::cout << "allocator type = " << typeid(A).name() << std::endl;
     std::cout << "container type = " << typeid(Container_t<T,A>).name() << std::endl;
   }
template <typename T>
void MyFunc2( T v ) {  }
int main()
{
   std::vector<char> v;
   MyFunc<char, std::allocator<char>, std::vector>(v);     // OK
   MyFunc(v);                        // now ok
}
If you don't care about anything except the value type and the container...
#include <vector>
#include <map>
#include <iostream>
#include <typeinfo>
template <
   typename T ,
   typename...Rest,
   template <typename, typename...> class Container_t
>
void MyFunc(Container_t<T, Rest...> &data) { 
     std::cout << "value type = " << typeid(T).name() << std::endl;
     std::cout << "container type = " << typeid(Container_t<T,Rest...>).name() << std::endl;
   }
template <typename T>
void MyFunc2( T v ) {  }
int main()
{
   std::vector<char> v;
   std::map<char, int> m;
//   MyFunc<char, std::allocator<char>, std::vector>(v);     // OK
   MyFunc(v);                        // now ok
   MyFunc(m);                        // now ok
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With