2016-06-07 7 views
5

Załóżmy, że mam jakieś listy typówDeklarowanie funkcji z typów argumentów zaczerpniętych z pakietem parametrów zagranicznych

template<typename... Types> struct TypeList {}; 

Teraz w innej klasie mogę wygenerować taki TypeList w różny sposób.

template<class T> struct MyClass { 
    using MyList = TypeList<T, typename Something<T>::type, SomethingElse>; 
    // ... 
}; 

Jak mogę zadeklarować metodę z typami argumentów wyodrębnionych z listy tego typu? Na przykład, jeśli ustawię wartość MyList = TypeList<int, float, const char*>, chcę zadeklarować deklarację metody.

+1

Co zamierzasz zrobić z funkcją nieznanego podpisu (np .: 'void my_method (T0, T1, T2, ... TN)' z N <= ogromnym)? –

+0

@ DieterLücking Liczne rzeczy! (Nie ma to znaczenia dla zadawanego pytania) –

Odpowiedz

4

Można czerpać z klasy bazowej, która implementuje metodę:

template <typename> struct MethodProvider; 

template <typename ...Args> 
struct MethodProvider<TypeList<Args...>> 
{ 
    void my_method(Args ...args); 
}; 

template <typename T> 
struct MyClassAux 
{ 
    using MyList = TypeList<T, typename Something<T>::type, SomethingElse>; 
}; 

template <typename T> 
struct MyClass 
    : private MyClassAux<T> 
    , private MethodProvider<typename MyClassAux<T>::MyList> 
{ 
    using typename MyClassAux<T>::MyList; 
    using MethodProvider<typename MyClassAux<T>::MyList>::my_method; 

    // ... 
}; 
+0

Wow, ładny schemat trzech klas. Czy to najprostszy możliwy sposób? –

+1

@TigranSaluev: To najprostsza rzecz * mogę * wymyślić, ale poczekaj i zobacz ... zauważ edycję, brakowało mi specjalizacji. –

+0

przy okazji, czy możliwe jest uzyskanie dostępu do innych metod i pól 'MyClass' z' my_method' w takim ustawieniu? –

0

Można użyć static_assert i std::is_same do przymusu argumenty my_method

#include <iostream> 
#include <string> 
#include <vector> 
#include <type_traits> 

template<typename... Types> struct TypeList {}; 

template<class T> struct MyClass { 
    using MyList = TypeList<int, T>; 

    template<typename ...Args> 
    void my_method(Args ...args) { 
     static_assert(std::is_same<MyList, TypeList<Args...>>::value, "invalid arguments"); 
     auto dummy = {(std::cout << args << "\n", 0)...}; 
     (void)(dummy); // avoid variable warning 
    } 
}; 

int main() 
{ 
    MyClass<float> c; 
    c.my_method(1, 2.3f); 
// c.my_method(1, ""); // unmatched arguments won't compile 
// c.my_method(1); 
} 

Online Demo

+1

Ta konwersja typu "zabija" podczas wywoływania metody, prawda? (Ponieważ będzie to po prostu "och, nie, to nie może być stałe T &, to powinno być dokładnie T!") –

+2

@ TigranSaluev Masz rację. Ale możesz użyć niestandardowej wersji 'std :: is_same', aby zwolnić ograniczenie przez' std :: decay' wszystkie typy jako pierwsze. –

+0

Naprawimy tylko najbardziej trywialne konwersje i nie naprawimy konwersji takich jak 'int' na' float'. –