Consider the following program.
#include <vector>
#include <unordered_set>
/**
* Convert any templated iterable container to a std::unordered_set.
*/
template <typename T>
std::unordered_set<T> vectorToUnorderedSet(const std::vector<T>& container) {
std::unordered_set<T> set;
for (T t: container) {
set.insert(t);
}
return set;
}
int main(){
std::vector<int> vec {1,2,3};
std::unordered_set<int> set = vectorToUnorderedSet(vec);
}
If I compile it with the following command, it compiles and runs fine.
g++ -std=c++11 -O3 -Wall -g TemplatePlay.cc -o TemplatePlay -pthread
Now, I'd like to generalize this function, so that it can take any templated container as input.
Here is my first attempt.
/**
* Convert any templated iterable container to a std::unordered_set.
*/
template <typename T, typename C>
std::unordered_set<T> containerToUnorderedSet(const C<T>& container) {
std::unordered_set<T> set;
for (T t: container) {
set.insert(t);
}
return set;
}
This fails with the following error.
g++ -std=c++11 -O3 -Wall -g TemplatePlay.cc -o TemplatePlay -pthread
TemplatePlay.cc:8:51: error: ‘C’ is not a template
std::unordered_set<T> containerToUnorderedSet(const C<T>& container) {
^
TemplatePlay.cc: In function ‘int main()’:
TemplatePlay.cc:18:60: error: no matching function for call to ‘containerToUnorderedSet(std::vector<int>&)’
std::unordered_set<int> set = containerToUnorderedSet(vec);
^
TemplatePlay.cc:8:23: note: candidate: template<class T, class C> std::unordered_set<T> containerToUnorderedSet(const C&)
std::unordered_set<T> containerToUnorderedSet(const C<T>& container) {
^~~~~~~~~~~~~~~~~~~~~
TemplatePlay.cc:8:23: note: template argument deduction/substitution failed:
TemplatePlay.cc:18:60: note: couldn't deduce template parameter ‘T’
std::unordered_set<int> set = containerToUnorderedSet(vec);
^
Next, I tried the magic incantations mentioned in this answer, but I don't understand the syntax, so it's possible that I implemented it incorrectly.
/**
* Convert any templated iterable container to a std::unordered_set.
*/
template <typename T, template <typename> class C>
std::unordered_set<T> containerToUnorderedSet(const C<T>& container) {
std::unordered_set<T> set;
for (T t: container) {
set.insert(t);
}
return set;
}
This resulted in the following error.
g++ -std=c++11 -O3 -Wall -g TemplatePlay.cc -o TemplatePlay -pthread
TemplatePlay.cc: In function ‘int main()’:
TemplatePlay.cc:18:60: error: no matching function for call to ‘containerToUnorderedSet(std::vector<int>&)’
std::unordered_set<int> set = containerToUnorderedSet(vec);
^
TemplatePlay.cc:8:23: note: candidate: template<class T, template<class> class C> std::unordered_set<T> containerToUnorderedSet(const C<T>&)
std::unordered_set<T> containerToUnorderedSet(const C<T>& container) {
^~~~~~~~~~~~~~~~~~~~~
TemplatePlay.cc:8:23: note: template argument deduction/substitution failed:
TemplatePlay.cc:18:60: note: template parameters of a template template argument are inconsistent with other deduced template arguments
std::unordered_set<int> set = containerToUnorderedSet(vec);
^
Makefile:8: recipe for target 'TemplatePlay' failed
make: *** [TemplatePlay] Error 1
If possible, what are the correct incantations for defining a templated method which takes a type requiring a template parameter?
The accepted answer to the question claimed as a duplicate does not address these compiler errors.