简体   繁体   中英

How to check for non primitive types in variadic templates?

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

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...);
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM