I'm still learning how to use variadic templates. Basically what I want to do is take an STLContainer
that contains elements of type String
. An STL container does not take a fixed number of parameters so I tried using a variadic template. If I understand correctly, I should be able to write this:
/* Take a container of String and return a string of those elements separated by commas.*/
template < template <typename String, typename ... Traits > class STLContainer >
String as_comma_list(const STLContainer<String, Traits> &container)
{
String result;
for (auto it = container.begin(); it != container.end(); it++)
{
result += *it;
result += ",";
}
result.pop_back(); // pop last comma
return result;
}
However the compiler (Apple LLVM version 8.1.0
) spits out:
error: use of undeclared identifier 'Traits'
Any help is much appreciated.
Edit: I ultimately have chosen @Pixelchemist's answer since it seems like the most "generic proof" solution and offered insight into my code. However, I would like to say that @Walter's answer is equivalently good. While @max66's answer was the simplest that fixed the problem, the original problem was that I tried to describe an STL container erroneously.
Your code would have to look like this:
but let's look at the implications of your code:
The type
STLContainer
must take a template parameter. If I write a classsimplestringvector
(which is not generic I know, but nobody can't stop me :)) your code won't work for me.The
STLContainer
type must providebegin()
andend()
members. (No free functions; nostd::begin
andstd::end
)The
String
type must provide apop_back()
member.The
String
type must haveoperator+=
defined which must be capable of dealing with a string literal containingchar
(nowchar_t
, nochar16_t
, ...).And others that are less of an issue here.
The function can be more generic:
No warranty as I'm quite tired but anyway...
If your code requires the type to be iterable anyway you don't need to know the type of the String in the first place. You can get it as the decayed result of dereferencing the container iterator. By dragging
std::begin
andstd::end
into the scope you can enable ADL for free begin and end functions while still catching the member functions via the std functions.First some headers and a helper class:
Now we try to implement
as_comma_list
with ADL enabled iteration and without any constraints with respect to the template layout of the container or string.Note: This example requires the String type to be iterable as well (which is very common) and it has a second branch in the loop which might be slower when dealing with billions of strings here.