Reputation: 43
I am trying to write a utility function called print()
, In which If a primitive type is passed, it just prints it and if a std::vector<int>
of primitive type is passed, it must loop through it and print it. I tried for a std::vector
of int
but failed miserably, primarily because I am not sure if this is allowed in c++. It would be much helpful if you could provide some generalized way to do it for vectors of all primitive types.
#include <iostream>
#include <vector>
#include <type_traits>
void print(std::ostream& out) {}
template <typename T, typename... Args>
void print(std::ostream& out, T type, Args... args)
{
if (std::is_same<T, std::vector<int>>::value) {
for (auto vector_iterator = type.begin();
vector_iterator != type.end(); ++vector_iterator) {
out << (*vector_iterator) << " ";
}
} else {
out << type;
}
print(out, args...);
}
int main()
{
std::vector<int> v {4,5,6};
print(std::cout, "bla", 1, 23.0, v);
return 0;
}
Here is the error that I encountered, if that helps:
util.cc: In instantiation of 'void print(std::ostream&, T, Args ...) [with T = const char*; Args = {int, double, std::vector<int, std::allocator<int> >}; std::ostream = std::basic_ostream<char>]':
util.cc:26:36: required from here
util.cc:11:42: error: request for member 'begin' in 'type', which is of non-class type 'const char*'
for (auto vector_iterator = type.begin();
^
util.cc:12:20: error: request for member 'end' in 'type', which is of non-class type 'const char*'
vector_iterator != type.end(); ++vector_iterator) {
Thanks
Upvotes: 1
Views: 217
Reputation: 66230
If you can compile C++17, you can use if constexpr
if constexpr (std::is_same<T, std::vector<int>>::value)
Before C++17 you have to develop different functions because the type.begin()
/type.end()
part is compiled also when value
is false (also when T
isn't a std::vector
).
A possible way to "split" the function is the following
template <typename... Args>
void print (std::ostream& out, std::vector<int> const & v, Args... args)
{
for (auto const & i : v)
out << i << ' ';
print(out, args...);
}
template <typename T, typename... Args>
void print (std::ostream& out, T type, Args... args)
{
out << type;
print(out, args...);
}
or, if you want to intercept different std::vector
types, you can templatize the type T
of the std::vector
and the first function become
template <typename T, typename... Args>
void print (std::ostream& out, std::vector<T> const & v, Args... args)
{
for (auto const & i : v)
out << i << ' ';
print(out, args...);
}
Upvotes: 4