First of all write a function that will process each pair (i.e. what you have inside your for loop):
using ImagePair = std::pair<SDL_Texture*&, const char*>;
void processImage(ImagePair imgPair)
{
SDL_Surface *curImage = IMG_Load(imgPair.second);
imgPair.first = SDL_CreateTextureFromSurface(ren, curImage);
SDL_FreeSurface(curImage);
}
Then if you have C++11 or above, you can use a brace-initialization trick to call processImage() for each argument:
template <typename ... Ts>
void loadImage(Ts ... ts)
{
using dummy = int[];
(void)dummy {0, (processImage(ts)), 0)... };
}
What you're doing here is taking advantage of the fact that the compiler knows it has to do a pack expansion inside a brace-initialization list. That way you can avoid having to write recursive variadic template functions yourself.
Here you are building a dummy array of integers, which is equal in size to the number of variadic arguments you pass in. For each argument you call the function processImage(), but using the comma operator you set the value in the array to 0. So you expand the pack and call processImage() for each argument while creating a dummy array. This answer might explain it more clearly.
If you have C++17 or above, you can simplify further and use a fold expression:
template<typename... Ts>
void loadImage(Ts... args)
{
(processImage(args),...);
}