2016-10-13 10 views
7

Powiedz, że mam klasę szablonu variadic. Jak utworzyć funkcję taką, że jej argumenty są typu ustawionego, na przykład int, z liczbą argumentów równą liczbie typów szablonów?Dla każdego szablonu wpisz argument typu zbioru

template <typename... Types> 
class Test 
{ 
public: 
    void Func(???); // I don't know how to declare such a function 
} 

Test<string, bool, long> myTest; // Three types 
myTest.Func(905, 36, 123315); // Three arguments, but always of type int. 

Ostatecznie celem tej funkcji jest zwrócenie krotki podanych int. Dla uproszczenia pokazałem, że funkcja jest nieważna w przykładowym kodzie.

+0

[W] (http://stackoverflow.com/questions/3703658/specifying-one-type-for-all-arguments-passed-to-variadic-function-or-variadic -te) z dodatkowym sprawdzeniem 'sizeof ...'? – LogicStuff

+0

Podoba Ci się to? http://ideone.com/PASclP –

+1

Nie potrzebujesz nawet "Typów", ponieważ rozmiar pakietu parametrów może zostać wywnioskowany przez połączenie: http://ideone.com/tPe6Tj –

Odpowiedz

17
template <typename... Types> 
class Test 
{ 
    template <typename> 
    using int_t = int; 

public:  
    void Func(int_t<Types>... ints) 
    { 
    } 
}; 

DEMO

+1

Sprytnie! Podoba mi się to rozwiązanie. –

+1

Pamiętaj, że twoje rozwiązanie umożliwia niejawne konwersje - nie wiesz, czy właśnie tego chce OP. –

+0

Czy mógłbyś wyjaśnić, jak to działa? Nigdy nie widziałem szablonu i używania w połączeniu. –

4

wandbox example - (działa z C++ 11)


Jeśli nie wymagają SFINAE, można użyć static_assert aby upewnić spełnione są twoje warunki:

template <typename... Types> 
class Test 
{ 
public: 
    template <typename... Ts> 
    void Func(Ts...) 
    { 
     static_assert(sizeof...(Ts) == sizeof...(Types), ""); 
     static_assert(std::conjunction<std::is_same<Ts, int>...>{}, ""); 
    } 
}; 

(Jeśli potrzebujesz SFINAE, użyj std::enable_if.)

std::conjunction sprawdza, czy wszystkie warunki przekazane do niego są prawdziwe.


Z powyższego przykładu, następujące połączenia są prawidłowe/nieprawidłowe:

myTest.Func(905, 36, 123315); // valid 
myTest.Func(905, 36, 123315.f); // invalid 
myTest.Func(905, 22); // invalid 

Jak widać, konwersje niejawne nie są akceptowane z tego rozwiązania. Możesz użyć std::is_convertible zamiast std::is_same, jeśli chcesz, aby były dozwolone.

+0

Plus 'conjunction' to C++ 17, ryzykowne ryzykowne. –

+1

@GillBates: można go łatwo zaimplementować, zobacz przykład na mojej skrzynce. Działa w C++ 11. –

+0

Zgadzam się, że twoje rozwiązanie w pełni rozwiązuje moje pytanie. Jednak rozwiązanie Piotra Skotnickiego wydaje się łatwiejsze do odczytania w mojej opinii i było (dla mnie) łatwiejsze do rozszerzenia na inne podobne zastosowania. W związku z tym wybieram jego odpowiedź jako najlepszą, mimo że bardzo mi pomogła. –

Powiązane problemy