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?
4 Réponses :
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>{})); };
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
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);
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 .
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 .
@Justin Bon point. Merci.