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.