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