Supposons que j'ai un std :: array
de doubles et que je souhaite qu'il soit converti en flottants:
const std::array<float, 100> f_array;
Si vous utilisez un std :: vector c'est extrêmement simple:
std::array<float, 100> f_array; std::copy(d_array.begin(), d_array.end(), f_array.begin());
Je sais que std :: array
est un type agreate, donc il semble que je doive faire un peu de manuel saute sur place pour copier le convertir en tableau ou y a-t-il un moyen pratique de le faire?
Je considère également std :: copy
passe-partout, par exemple:
std::vector<float> f_array(d_array.begin(), d_array.end());
Ce n'est pas plus simple que la version vectorielle et ne peut pas être const :
std::array<double, 100> d_array{1,2,3}; std::array<float, 100> f_array; <--convert it from d_array;
Ainsi ruinant le code autrement corrigé par const.
3 Réponses :
Je doute qu'il y ait une solution en une seule ligne, mais en deux lignes:
std::array<float, 100> f_array; std::copy(d_array.begin(), d_array.end(), f_array.begin());
Voir std :: copy
.
Cela ne fonctionnera pas avec une version const, par exemple. const std :: array
@darune Si vous avez besoin d'initialiser un const std :: array
de cette façon, vous devrez envelopper l'initialisation dans une fonction ou lambda qui renvoie le tableau
. La "version vectorielle" n'est pas pertinente. Si vous pensez qu'un std :: array
est meilleur qu'un std :: vector
pour vos besoins, vous ne pouvez pas utiliser std :: vector code > fonctions. Les conteneurs ont des interfaces différentes car ce sont des choses différentes.
C'est ce que cette question porte. J'essaie d'éviter d'utiliser lambda, passe-partout, quoi que ce soit et à la recherche d'une façon plus propre de le faire (ou boost, ou même c ++ 20). Je prends votre commentaire comme: ce n'est pas possible.
"Comment puis-je construire une bibliothèque sans utiliser d'outils? C'est facile si je construis un sandwich."
Vous pouvez écrire une fonction de conversion simple. Il n'y a pas de fonctions standard ou boost existantes à ma connaissance, mais c'est assez simple à implémenter:
template <typename T, typename U, size_t N, size_t... Is> std::array<T, N> array_cast(const std::array<U, N>& arr, std::index_sequence<Is...>) { return { static_cast<T>(arr[Is])... }; } template <typename T, typename U, size_t N> std::array<T, N> array_cast(const std::array<U, N>& arr) { return array_cast<T>(arr, std::make_index_sequence<N>()); }
Pour l'utiliser, il suffit d'appeler array_cast
p>
C'est en fait une excellente idée. Je laisse la question ouverte un peu pour voir si les autres répondent.
@darune: Notez que cette solution est limitée aux valeurs de N
que votre compilateur prendra en charge l'utilisation de modèles variadiques.
Alors que Miles Budnek de answer résout le problème d'OP, il peut échouer si le tableau est trop grand (notez que vous demandez au compilateur de générer et d'exécuter une fonction avec N paramètres). Voir par exemple cet exemple .
Une alternative pourrait être d'utiliser un simple pour
loop, qui, depuis C ++ 14, est autorisée dans les fonctions constexpr
.
template< class R, class T, size_t N> constexpr std::array<R, N> array_copy(std::array<T, N> const &src) { std::array<R, N> tmp {}; for (size_t i{}; i < N; ++i) tmp[i] = static_cast<R>(src[i]); return tmp; }
Live ICI .
@darune Absolument, vous avez raison. Fixé, merci. C'est drôle (et très instructif) comment de mauvais tests peuvent cacher des bugs désagréables.
Vous dites "Si vous utilisez un std :: vector c'est extrêmement simple" alors pourquoi pas vous?
@nada c'est comme dire, pourquoi utiliser un
std :: array
quand le vecteur existe ...N'oubliez pas que
float
a des plages de valeurs nettement plus petites quedouble
...«évident» est un terme difficile à mon humble avis. Quelle est la mise en œuvre "évidente"? Pensez-vous déjà utiliser
std :: copy
comme passe-partout?@darune Non, c'est comme dire "Si dans votre cas std :: vector correspond mieux, alors pourquoi ne pas l'utiliser".
@nade mais ce n'est pas ainsi que j'ai défini la question.
Que considérez-vous comme passe-partout? Une fonction de conversion que vous pouvez écrire une fois et ranger dans un en-tête quelque part compterait-elle comme passe-partout? C'est le seul moyen auquel je peux penser pour éviter un encombrement supplémentaire sur le site de conversion, mais il n'y a pas de fonction de conversion standard à ma connaissance.
@MilesBudnek c'est une réponse acceptable si c'est le cas. Une solution impliquant boost, c ++ 20 est également acceptable.