2013-04-08 2 views
3

Предположим, что я хочу что-то испытывать с vector<int>, vector<bool>, vector<string>. Я хочу написать примерно так:Зацикливание по типам

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

Я знаю, что на этом языке нет такой функции, но можно ли как-то подражать? Есть ли этот функционал в некоторой библиотеке, например boost?

ответ

6

Boost.MPL

можно выполнить с списками типов - они подробно обсуждаются в Modern C++ Design: Generic Programming and Design Patterns Applied по Александреску

Check Boost.MPL библиотека. Например - 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()); 
} 

Выход:

Testing int 
Testing bool 
Testing std::string 

C++ 11 VARIADIC Шаблоны

Другой вариант заключается в использовании C++ 11 VARIADIC шаблоны :

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()); 
} 
+0

BOOST.MPL абсолютно для меня достаточно, но 1 проблема, которая может быть интересной: она не работает (http://liveworkspace.org/code/2TZHbN$4), не имеющая стандартных конструкций (если я тестирую это правильно) – RiaD

+0

В таком случае быстрое решение - это просто [использовать указатели] (http://liveworkspace.org/code/sChpB$0) –

+0

Означает ли это, что вызываются конструкторы векторных элементов? @EvgenyPanasyuk: Ваша ссылка не работает для меня. Я полагаю, вы говорите об одной и той же проблеме и предлагаете звонить с типами указателей вместо этого? – Syncopated

0

мне удалось сделать то, что работает, но это не очень красиво и работает только с по умолчанию-costructable типов:

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()); 
} 
+0

Проверить botton [мой ответ] (http://stackoverflow.com/a/15869682/1762344) - У меня есть второй подход, основанный на вариативных шаблонах - он не требует конструктивности по умолчанию –

1

Это использует VARIADIC шаблоны для достижения этой цели:

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

Демонстрация here.

+1

Можно сделать [без рекурсии ] (http://liveworkspace.org/code/yOEFa$11): auto && t = {(do_test (), 0) ...}; –

+0

@ EvgenyPanasyuk приятно! – mfontanini

Смежные вопросы