2014-05-17 9 views
5

Una tipica implementazione sarebbe in questo modo:test se un tipo V è uno dei tipi di una tupla <...> senza variardics

template <typename V, typename T> 
struct Is_in_tuple; 

template <typename V, typename T0, typename... T> 
struct Is_in_tuple <V, tuple<T0, T...> > 
{ 
    static const bool value = Is_in_tuple<V, tuple<T...> >::value; 
}; 

template <typename V, typename... T> 
struct Is_in_tuple <V, tuple<V, T...> > 
{ 
    static const bool value = true; 
}; 

template <typename V> 
struct Is_in_tuple <V, tuple<> > 
{ 
    static const bool value = false; 
}; 

Il problema si pone in VS2012 cui esistono tuple, ma templates variadic non!

C'è una soluzione alternativa, un modo per eseguire tali test senza modelli variadic?

+0

Come può un compilatore supportare in modo decente le tuple senza supportare i modelli variadic? – BatchyX

+0

@BatchyX: limite superiore e generazione automatica simili a Boost.Preprocessor. – Xeo

+0

@Xeo: ho detto che, per quanto mi riguarda, sono conforme allo standard. – BatchyX

risposta

3

Purtroppo, non posso testarlo su MSVC2012 adesso.

#include <type_traits> 
#include <tuple> 

template<class Needle, class Haystack, int N = std::tuple_size<Haystack>::value> 
struct is_any_of 
    : std::integral_constant 
     < 
      bool, 
      (std::is_same<Needle, typename std::tuple_element<N-1, Haystack>::type> 
      ::value 
      || is_any_of<Needle, Haystack, N-1>::value) 
     > 
{}; 

template<class Needle, class Haystack> 
struct is_any_of<Needle, Haystack, 0> 
    : std::false_type 
{}; 

#include <iostream> 
int main() 
{ 
    typedef std::tuple<int, int, char, int, int> t0; 
    typedef std::tuple<int, int, int, int, int> t1; 

    std::cout << std::boolalpha << is_any_of<char, t0>::value << "\n"; 
    std::cout << std::boolalpha << is_any_of<char, t1>::value << "\n"; 
} 
4

Se VS2012 supporta tuple_size e tuple_element, si possono usare al posto (codice completamente non testato):

template <typename V, typename T, size_t T_end = std::tuple_size<T>::value> 
struct Is_in_tuple 
    : std::conditional<std::is_same<V, typename std::tuple_element<T_end-1,T>::type>::value, 
        std::true_type, Is_in_tuple<V, T, T_end - 1>>::type {}; 

template <typename V, typename T> 
struct Is_in_tuple <V, T, 0> : std::false_type {}; 
+0

Il vantaggio di questa versione rispetto alla mia è che non produce istanze superflue, poiché può interrompere la creazione di istanze presto a causa di 'std :: condizionale'. Se questo è più veloce o meno deve essere misurato, naturalmente. – dyp

+0

@dyp: modificato. Non vedo perché rompa l'istanza. 'std :: condizionale' richiede ancora la valutazione di tutti i suoi argomenti. Ho esitato a includere l'elemento tuple valutato come un altro parametro per evitarlo, ma puzza quando la dimensione raggiunge lo zero e non volevo aggiungere un altro modello – BatchyX

+0

[Esempio dal vivo] (http://coliru.stacked-crooked.com/ a/3232e8a7892b3640) – dyp

0

Un approccio completamente diverso si basa sul limite di dimensioni.

Contiamo sul numero massimo di argomenti, che è da 5 a 10 se ricordo correttamente.

Scriviamo una specializzazione per ogni dimensione oltre a 0 e 1 che invoca tuple di dimensioni più piccole (metà, per ricorsione minima), || il risultato di ciascuna metà.

Quindi scriviamo le specializzazioni <T> e <>.

Ripiega su questo se le altre soluzioni falliscono, poiché smette di funzionare nel momento in cui ottieni una tupla conforme agli standard, o addirittura cambia il simbolo del preprocessore del numero massimo di elementi per una tupla.

Problemi correlati