Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nested templates function taking 2 containers with the same inner type

Tags:

c++

templates

I am trying to write function which is roughly similar to a function that takes two instances of containers (let's say for now they are the same), containing same type and merges them. So here's my function for vectors:

template<typename T>
void test(std::vector<T> v1, std::vector<T> v2) {
  std::cout << "called nested for c\n";
}

and it works.

Now I want to have one that would work for sets or vectors. And I try this:

template<typename T, template <typename> typename C >
void test(C<T> v1, C<T> v2) {
  std::cout << "called nested for c<t>\n";
}

and get

nestedt.cc:33:6: note: template argument deduction/substitution failed: nestedt.cc:43:12: error: wrong number of template arguments (3, should be 1) test(s, s); ^ nestedt.cc:32:51: note: provided for ‘template class C’ template typename C > ^

I try

template< template <typename T> typename C >
void test(C<T> v1, C<T> v2) {}

std::set<int> s = {1,2};
test(s, s);

and that doesn't work:

nestedt.cc:32:6: note: template argument deduction/substitution failed: nestedt.cc:42:12: note: cannot convert ‘s’ (type ‘std::set’) to type ‘int’ test(s, s); ^

So I try

template<typename C, typename T >
void test(C<T> v1, C<T> v2) {}

and get

nestedt.cc:32:6: note: candidate: template void test(C, C) void test(C v1, C v2) { ^ nestedt.cc:32:6: note: template argument deduction/substitution failed: nestedt.cc:42:12: note: couldn't deduce template parameter ‘T’ test(s, s); ^

I feel like I'm not even close to understanding how templates actually work in C++ and it is so sad. Also in reality I want the containers to be different. And ideally be able to somehow specify a limited set of allowed containers. And they are not really std:: containers.

Note that the final goal is to be able to take 2 different containers, so something like test(vector<int>, set<int>). And modifying the containers is kind of impossible.

like image 842
MK. Avatar asked Mar 26 '26 10:03

MK.


1 Answers

I believe what you are looking for is

template<template <typename...> typename Cont1, 
         template <typename...> typename Cont2,
         typename... T>
void test(Cont1<T...> a, Cont2<T...> b) { }

In the above template <typename...> typename Cont1 declares one template template type and template <typename...> typename Cont2 declares another one so you can have two different container types. The both share T... so each template container needs to have a matching template parameter list. This means

test(std::map<int, int>{}, std::map<int, int>{});
test(std::set<int>{}, std::set<int>{});
test(std::vector<int>{}, std::set<int>{});

all work but

test(std::map<int, int>{}, std::vector<int>{});
test(std::map<int, int>{}, std::set<int>{});

wouldn't.

like image 197
NathanOliver Avatar answered Mar 31 '26 04:03

NathanOliver