Reputation: 418
I have the following code, the problem is when I try to pass basic_string type to writeContainer function it gives me error it read the type Cont as std::_String_val< std::_Simple_types > so it give me errors like there is no size() method, and does not have end() or begin() methods for for each loop.
the nice thing, when I use vector it works fine, even though they are the same concept !! any help appreciated
template< template<typename> class Cont, typename T >
void writeContainer(Stream& stream, const Cont<T>& outValue) {
stream << (int32_t)outValue.size();
for (auto& v : outValue) {
stream << v;
}
}
template<typename T>
Stream& operator<<(Stream& stream, const basic_string<T>& outValue) {
writeContainer(stream, outValue);
return stream;
}
errors I get, I use VS2013
error C2039: 'size' : is not a member of 'std::_String_val<std::_Simple_types<char>>'
see reference to function template instantiation 'void writeContainer<std::_String_val,std::_Simple_types<char>>(Stream &,const std::_String_val<std::_Simple_types<char>> &)' being compiled
see reference to function template instantiation 'Stream &operator <<<char>(Stream &,const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &)' being compiled
error C3312: no callable 'begin' function found for type 'const std::_String_val<std::_Simple_types<char>>'
error C3312: no callable 'end' function found for type 'const std::_String_val<std::_Simple_types<char>>'
error C2065: 'v' : undeclared identifier
Upvotes: 0
Views: 818
Reputation: 52471
For a template template parameter, the argument must be a class template with the exact same number of parameters - counting parameters that have defaults. Thus, even though std::vector
can be instantiated with one argument, it's a two-parameter template (the second parameter has a default), and cannot be an argument for Cont
. Similarly, std::basic_string
is a three-parameter template.
What happens in your example is this. In this particular implementation, std::basic_string
is derived from an internal class called _String_val
which, by unlucky coincidence, just happens to be a one-parameter template. So Cont
is deduced to be _String_val
, but then the instantiation fails as _String_val
does not have a method named size
(that method is implemented by basic_string
itself).
Despite your claim to the contrary, I get a similar error when using std::vector
in place of std::basic_string
- for the exact same reason.
Now, there's no reason to make Cont
a template template parameter (and a good reason not to - it won't work). Make it a plain type parameter, or else have the function take a pair of iterators. Something along these lines:
template<typename Cont>
void writeContainer(Stream& stream, const Cont& outValue);
// or
template<typename Iter>
void writeRange(Stream& stream, Iter first, Iter last);
Upvotes: 2