RiaD
RiaD

Reputation: 47619

Looping through number of types

Suppose I want test something with vector<int>, vector<bool>, vector<string>. I want to write something like this:

for(type T in {int, bool, string}){
   vector<T> v;
   for(int i = 0; i < 3; ++i){
       v.push_back(randomValue<T>());
   }
   assert(v.size() == 3);
}

I know there isn't such feature in the language but is it possible to emulate somehow? Is there this functional in some library, for example boost?

Upvotes: 3

Views: 162

Answers (3)

Evgeny Panasyuk
Evgeny Panasyuk

Reputation: 9199

Boost.MPL

It is possible to accomplish with typelists - they are discussed in details in Modern C++ Design: Generic Programming and Design Patterns Applied by Andrei Alexandrescu

Check Boost.MPL library. For instance - boost::mpl::for_each

LIVE DEMO

#include <boost/exception/detail/type_info.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector.hpp>
#include <iostream>
#include <cassert>
#include <vector>
#include <string>

using namespace boost;
using namespace std;

template<typename T>
T randomValue()
{
    return T();
}

struct Benchmark
{
    template<typename T>
    void operator()(T) const
    {
        cout << "Testing " << type_name<T>() << endl;
        vector<T> v;
        for(int i = 0; i < 3; ++i)
        {
           v.push_back(randomValue<T>());
        }
        assert(v.size() == 3);
    }
};

int main()
{
    mpl::for_each<mpl::vector<int, bool, string>>(Benchmark());
}

Output is:

Testing int
Testing bool
Testing std::string

C++11 Variadic Templates

Another option is to use C++11 variadic templates:

LIVE DEMO

#include <boost/exception/detail/type_info.hpp>
#include <iostream>
#include <cassert>
#include <vector>
#include <string>

using namespace boost;
using namespace std;

template<typename T>
T randomValue()
{
    return T();
}

struct Benchmark
{
    template<typename T>
    void operator()(T) const
    {
        cout << "Testing " << type_name<T>() << endl;
        vector<T> v;
        for(int i = 0; i < 3; ++i)
        {
           v.push_back(randomValue<T>());
        }
        assert(v.size() == 3);
    }
};

template<typename ...Ts,typename F>
void for_each(F f)
{
    auto &&t = {(f(Ts()),0)...};
    (void)t;
}

int main()
{
    for_each<int, bool, string>(Benchmark());
}

Upvotes: 6

mfontanini
mfontanini

Reputation: 21900

This uses variadic templates to achieve that:

template<typename T>
void do_test(){
   // do the actual testing here, for type T
}

template<typename T>
void test_vectors() {
    do_test<T>();
}

template<typename T, typename Head, typename... Tail>
void test_vectors() { 
    do_test<T>();
    test_vectors<Head, Tail...>();
}

Demo here.

Upvotes: 1

RiaD
RiaD

Reputation: 47619

I've managed to do something that works, but isn't very beautiful and works only with default-costructable types:

void loop() {
}

template<typename T, typename... Args>
void loop(T t, Args... args) {
    cerr << "work with " << typeid(T).name() << endl;
    loop(args...);
}
int main() {
    loop(int(), char(), vector<int>(), string());
}

Upvotes: 0

Related Questions