4
votes

définir un type de coordonnées variadiques (tuple) en C ++ 17?

Je voulais définir un type de tuple variadique pour représenter les coordonnées. Par exemple, pour un type magique:

std::tuple<double, double, double>

Je voudrais que CoordT :: coord_type soit le type de coordonnées en 3 dimensions: p>

template <unsigned int N>
struct CoordT {
  typedef std::tuple<_some_magic_> coord_type;
};

.

Mais je ne sais pas comment utiliser la programmation de modèle pour générer N double code répété > s.

Quelqu'un peut-il expliquer comment l'écrire?


1 commentaires

@Justin Bon point. Merci.


4 Réponses :


3
votes

Utilisez std :: make_integer_sequence pour générer un pack de la longueur appropriée, puis mappez les éléments en doubles:

template <size_t n>
struct TupleOfDoubles {
    template <size_t... i>
    static auto foo(std::index_sequence<i...>) {
        return std::make_tuple(double(i)...);
    }
    using type = decltype(foo(std::make_index_sequence<n>{}));
};

http://coliru.stacked-crooked.com/a/7950876813128c55


2 commentaires

Merci! Pourriez-vous ajouter un exemple sur la façon d'utiliser la fonction foo pour créer un tuple de doubles?


@tinlyx vérifie le lien coliru



0
votes

Est-il trop tard pour jouer?

Si pour vous il est acceptable de déclarer (aucune définition n'est nécessaire) une fonction de modèle variadique comme suit

#include <tuple> 
#include <type_traits> 

template <std::size_t ... Is>
constexpr auto toIndexSeq (std::index_sequence<Is...> a)
   -> decltype(a);

template <std::size_t N,
          typename = decltype(toIndexSeq(std::make_index_sequence<N>{}))>
struct CoordT;

template <std::size_t N, std::size_t ... Is>
struct CoordT<N, std::index_sequence<Is...>>
 { using coord_type = std::tuple<decltype((void)Is, 0.0)...>; };


int main()
 {
   using t0 = std::tuple<double, double, double, double>;
   using t1 = typename CoordT<4u>::coord_type;

   static_assert( std::is_same<t0, t1>::value, "!" );
 }

et que le coord_type est défini dans une spécialisation CoordT , vous pouvez l'écrire comme suit

template <std::size_t N,
          typename = decltype(toIndexSeq(std::make_index_sequence<N>{}))>
struct CoordT;

template <std::size_t N, std::size_t ... Is>
struct CoordT<N, std::index_sequence<Is...>>
 { using coord_type = std::tuple<decltype((void)Is, 0.0)...>; };

Ce qui suit est un C ++ complet 14 exemple de compilation

template <std::size_t ... Is>
constexpr auto toIndexSeq (std::index_sequence<Is...> a)
   -> decltype(a);


0 commentaires

2
votes

Si vous n'avez pas besoin littéralement d'un std :: tuple , mais simplement de quelque chose qui agit comme un tuple, utilisez std :: array :

template <unsigned int N>
struct CoordT {
  typedef std::array<double, N> coord_type;
};

std :: array code> a des surcharges pour std :: get code > , std :: tuple_size et std :: tuple_element a>. La plupart des bibliothèques et des langages acceptant un élément de type tuple prendront en charge std :: array , comme std :: apply et liaisons structurées .


0 commentaires

0
votes

Une manière très concise d'y parvenir consiste à utiliser std: : tuple_cat et std :: array code> :

template <unsigned int N>
struct CoordT {
  using coord_type = decltype(std::tuple_cat(std::array<double, N>{}));
};

std :: tuple_cat est autorisé à prendre en charge les types de type tuple tels que std :: array , mais pas garanti. Cependant, chaque implémentation que j'ai vérifiée prend en charge cela .


0 commentaires