template template : no matching function for call

this code compile fine in the old compiler (RAD studio XE4)

in version 10.3 i get this error:

error: no matching function for call to 'VectorMove'
note: candidate template ignored: substitution failure


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <list>
#include <deque>
#include <vector>
#include <iterator>
#include <algorithm>
#include <type_traits>

#define IsList(V, T)      std::is_same< V<T>, std::list<T> >::value
#define IsDeque(V, T)     std::is_same< V<T>, std::deque<T> >::value
#define IsVector(V, T)    std::is_same< V<T>, std::vector<T> >::value

//---------------------------------------------------------------------------

template <template <typename> class V, typename T> void VectorMove(V <T> & Vector, int FromIndex, int ToIndex)
{
	static_assert(IsList(V, T) || IsDeque(V, T) || IsVector(V, T), "Vector must be a container type.");
	class V<T>::iterator it1, it2, it3;
	it1 = it2 = it3 = Vector.begin();
	std::advance(it1, FromIndex);
	std::advance(it2, FromIndex + 1);

	if (FromIndex > ToIndex)
	{
		std::advance(it3, ToIndex);
		std::rotate(it3, it1, it2);
	}
	else
	{
		std::advance(it3, ToIndex + 1);
		std::rotate(it1, it2, it3);
	}
}
//---------------------------------------------------------------------------

void zTest()
{
    std::vector <int> qwe(5, 0);
    VectorMove(qwe, 0, 1);
}
//--------------------------------------------------------------------------- 
Last edited on
error: wrong number of template arguments (2, should be 1)

std::vector has two template parameters, element type and allocator.
I guess it needs to know these even though the allocator defaults to std::allocator<T>?

This should compile for you:
1
2
3
4
5
6
7
8
9
10
11
#define IsList(V, T)      std::is_same< V<T, Allocator>, std::list<T> >::value
#define IsDeque(V, T)     std::is_same< V<T, Allocator>, std::deque<T> >::value
#define IsVector(V, T)    std::is_same< V<T, Allocator>, std::vector<T> >::value

//---------------------------------------------------------------------------

template <typename T, typename Allocator, template<typename, typename> class V>
void VectorMove(V <T, Allocator> & Vector, int FromIndex, int ToIndex)
{
	static_assert(IsList(V, T) || IsDeque(V, T) || IsVector(V, T), "Vector must be a container type.");
	class V<T, Allocator>::iterator it1, it2, it3;

(Keep the rest the same. Guess you could make the Allocator a macro argument as well.)

I'm not exactly sure why it can't assume the default template parameter argument. There might be a cleaner way to do this.
Last edited on
Consider something like this
1
2
3
4
5
6
template<template<typename...> class, typename...>
  constexpr bool is_specialization_of = false;
template<template<typename...> class U, typename... T> 
  constexpr bool is_specialization_of<U, U<T...>> = true;
template <typename T> 
  constexpr bool is_vector = is_specialization_of<std::vector, T>;
1
2
3
4
5
6
7
8
9
10
11
#define IsList(V, T)      std::is_same< V<T, Allocator>, std::list<T> >::value
#define IsDeque(V, T)     std::is_same< V<T, Allocator>, std::deque<T> >::value
#define IsVector(V, T)    std::is_same< V<T, Allocator>, std::vector<T> >::value

//---------------------------------------------------------------------------

template <typename T, typename Allocator, template<typename, typename> class V>
void VectorMove(V <T, Allocator> & Vector, int FromIndex, int ToIndex)
{
	static_assert(IsList(V, T) || IsDeque(V, T) || IsVector(V, T), "Vector must be a container type.");
	class V<T, Allocator>::iterator it1, it2, it3;



thanks, it works
except

typename V<T, Allocator>::iterator it1, it2, it3;
instead of class
Ganado wrote:
I guess it needs to know these even though the allocator defaults to std::allocator<T>?


This was actually fixed in C++17. OP seems to be compiling on a version lower than C++17, which is why he is getting that error. In order to make it work on something lower than C++17, you could fix it by making a variadic argument

template <template <typename...> class V, typename T> void VectorMove(V <T> & Vector, int FromIndex, int ToIndex)

But when I tested it, it seems to work on C++17 without the variadic template just fine.
Last edited on
Thanks I think you're right.
Topic archived. No new replies allowed.