0
votes

Comment convertir std :: array en std :: array ? (évitant une mise en œuvre passe-partout évidente)

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 :

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.


8 commentaires

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 que double ...


«é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.


3 Réponses :


3
votes

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 .


4 commentaires

Cela ne fonctionnera pas avec une version const, par exemple. const std :: array . De plus, la version vectorielle est encore plus simple.


@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 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."



3
votes

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 (d_array)

Exemple

p>


2 commentaires

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.



2
votes

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 .


1 commentaires

@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.