Comment éviter les conversions implicites de int (0) en pointeur dans un vecteur

9

Il y a une situation où je veux collecter tous les noms de nœuds d'un chemin d'accès à une clé dans JSON. Tenez compte de la condition de l'index du tableau "0", "1" sont également autorisés, mais il est facile d'oublier les guillemets, ce qui conduirait à un crash lors de la déréférence. Je veux donc rejeter cela. Exemple:

#include <vector>
#include <iostream>

int func(const std::vector<const char*>& pin) {
    return pin.size();
}

int main() {
    // {"aname", "3", "path", "0"} wanted but this still compile
    std::cout << func({"aname", "3", "path", 0}) << std::endl;
}

J'ai trouvé et essayé ceci Comment éviter les conversions implicites sur des fonctions non constructives? comme suit:

#include <vector>
#include <iostream>

int func(const std::vector<const char*>& pin) {
    return pin.size();
}

template<typename T>
int func(T pin) = delete;

int main() {
    std::cout << func({"aname", "3", "path", 0}) << std::endl;
}

Mais le compilateur ne m'a toujours pas compris.

Toute suggestion?
Veuillez signaler toute utilisation abusive des terminologies et des hypothèses, merci!

rustyhu
la source
y a-t-il une raison pour laquelle vous utilisez à la std::vector<const char*>place de std::vector<std::string>>?
bolov
Voulez-vous nullptraussi interdire ?
Jarod42
@bolov Au début, je pense à passer ces noms de nœuds à une interface d'analyse JSON, qui utilise le caractère de style C * en entrée, mais cela n'est pas limité ici. J'ai testé, en utilisant std :: vector <std :: string >> accepte toujours 0 lors de la compilation, mais se bloque lors de l'exécution, sur ma machine GCC signale "basic_string :: _ M_construct null non valide".
rustyhu
@ Jarod42 Oui, ce que nous voulons, c'est un littéral de chaîne de style C.
rustyhu

Réponses:

9

Quelque chose comme ça? Elle est très similaire à la solution de surcharge que vous avez suggérée, mais nécessite un habillage du type de vecteur. Échec de la construction si vous fournissez un littéral 0car la surcharge de constructeur supprimée est choisie.

#include <memory>
#include <new>
#include <vector>
#include <iostream>
using std::vector;

template<typename T>
struct no_zero {
        no_zero(T val) : val(val) {}
        no_zero(int val) = delete;
        operator T() { return val; }
        T val;
};

int func(const vector<no_zero<const char*> >& pin) {
    return pin.size();
}

int main() {
    // {"aname", "3", "path", "0"} wanted but this still compile
    std::cout << func({"aname", "3", "path", 0}) << std::endl;
}
Mikel Rychliski
la source
4

Avec le recul, la plupart des conversions implicites en C ++ sont regrettables, ceci étant l'un d'entre eux.

Une option à considérer est -Wzero-as-null-pointer-constantsur gcc et clang. Soyez prudent car cela modifie le comportement des programmes standard et, s'il est activé globalement, peut avoir des effets inattendus.

g ++ - comment désactiver la conversion implicite de 0 en types de pointeurs?

Quel avertissement Clang est équivalent à Wzero-as-null-pointer-constant de GCC?

bolov
la source