Thomas Thomas - 2 months ago 16
C++ Question

Non-last parameter pack compilation error

I am trying to understand how parameter packs work in variadic template functions when they are not the last parameter. I don't get why some of my calls in my sample code doesn't work. The questions are in the comments. Should they work or I don't understand something or VS2015 update 3's compiler doesn't support them yet?

template <typename T>
double sum(T t) {
return t;
}

template <typename T, typename... Rest>
double sum(Rest... rest, T t) {
return t + sum(rest...);
}

template <typename T>
double sum2(T t) {
return t;
}

template <typename T, typename... Rest>
double sum2(T t, Rest... rest) {
return t + sum2(rest...);
}

template<typename... Args>
void func(Args..., int = 0)
{}

void func()
{
func<int, int, int>(1, 1, 1);
func(1, 1, 1); // why doesn't this compile?
sum(1, 1); // why doesn't this compile?
sum<int, int>(1, 1);
sum<int, int, int>(1, 1, 1); // why doesn't this compile while func<int, int, int>(1, 1, 1) does?

// why are these compile? I only changed the order of the parameters compared to sum()
sum2(1);
sum2(1, 1);
sum2(1, 1, 1);
}

Answer

I'm not really an expert but, as far I know...

func(1, 1, 1); // why doesn't this compile?

Because, in a function template, the types of a parameter pack can be deduced only if it's in last position.

The first call

func<int, int, int>(1, 1, 1);

works because the types of the parameter aren't deduced but are explained (Args... is int, int, int) and func() receive a fourth int (with default value zero)

The call

func<int, int>(1, 1, 1);

works also because Args... is explained as int, int and the func() function receive a third int with not default value 1


sum(1, 1); // why doesn't this compile?

Same reason: the parameter pack isn't in last position so can't be deduced; but works

sum<int, int>(1, 1);

because T is explicated as int and Rest... as int also.


sum<int, int, int>(1, 1, 1); // why doesn't this compile while func<int, int, int>(1, 1, 1) does?

The fist level call works because T is explicated as int and Rest... as int, int; but sum<int, int, int>(1, 1, 1) call sum(rest...) that, in this case is sum(1, 1); it's sum(1, 1) that fail because Rest... isn't in last position so can't be deduced


// why are these compile? I only changed the order of the parameters compared to sum()
sum2(1);
sum2(1, 1);
sum2(1, 1, 1);

Because in sum2() the parameter pack list Rest... is in last position so can be (and is) deduced.