2016-07-08 9 views
5

Jestem dość niedoświadczony w takich rzeczach, ale próbuję utworzyć funkcję szablonu, która ocenia zmienną funkcję przy argumentie "obróconym" (patrz przykład poniżej) i zwraca wektor wszystkich tych wartości.C++ variadic szablon argument iteracyjny

Na przykład n = 3, z funkcją f (x, y, z), zwrócony potrójne \ wektorów należy

< f (x, 0,0), f (0, x, 0), f (0,0, x)>

naiwna wersja tego, co muszę mógłby wyglądać następująco (nie niez sary correct \ working)

typedef FunctionSignature Function; 

template<class Function, size_t Dimensions> 
std::array<Function::Out,Dimensions> F(Function::InComponent x) 
{ 
    std::array<Function::Out,Dimensions> Result; 

    for (i=0; i<Dimensions; i++)  
    Result[i] = Function::f("rotate((x,0,...,0),i)"); 

    return Result; 
} 

Ale jak zrobić rzecz rotate.

Mam również nadzieję, że programowanie for może być w jakiś sposób wyeliminowane, ponieważ n jest dobrze znane w czasie kompilacji.

+0

Zamiast funkcji 'f()' przyjmującej jawną listę wartości jako parametry, należy zamiast tego użyć funkcji 'f()' zamiast wektora wartości. Wypełnienie wektora wartościami, które mają być przekazane jako parametr, staje się trywialne. Nie ma potrzeby radzenia sobie z funkcjami variadycznymi. –

+0

1) Nie mam problemu z "wycenieniem" wektora "f", jak sądzę ... chociaż może to być zbędne, gdy "n" = 1. .... 2) "staje się trywialne" nie pomaga ... szczególnie, nie jestem pewien, jak to pomaga, aby to zrobić w czasie kompilacji. –

Odpowiedz

5
template<class Function, size_t... Is, size_t... Js> 
typename Function::Out call_f(typename Function::InComponent x, 
           std::index_sequence<Is...>, 
           std::index_sequence<Js...>) { 
    return Function::f((void(Is), 0)..., x, (void(Js), 0)...); 
} 

template<class Function, size_t Dimensions, size_t... Is> 
std::array<typename Function::Out, Dimensions> F(typename Function::InComponent x, 
               std::index_sequence<Is...>) 
{ 
    return {{ call_f<Function>(x, std::make_index_sequence<Is>(), 
           std::make_index_sequence<Dimensions - Is - 1>())... }}; 
} 

template<class Function, size_t Dimensions> 
std::array<typename Function::Out,Dimensions> F(typename Function::InComponent x) 
{ 
    return F<Function, Dimensions>(x, std::make_index_sequence<Dimensions>()); 
} 

Dla języka C++ 11 wyszukaj wartość SO dla implementacji make_index_sequence.

Demo.

+0

Dzięki, wygląda to bardzo ładnie i dokładnie to, czego potrzebuję! (z wielką nadzieją, że wiem, czego potrzebuję sam, lol) –

+0

Przypuszczam, że '(void (Is), 0) ...' powinno być '(void (Is), Function :: InComponent (0)). ..' w całkowicie ogólnym przypadku –