Come evitare conversioni implicite da int (0) al puntatore in un vettore


9

C'è una situazione in cui voglio raccogliere tutti i nomi dei nodi di un percorso di una chiave in JSON. Considera anche le condizioni dell'indice di array "0", "1", ma è facile dimenticare le virgolette, che porterebbe a un arresto anomalo quando si verifica la dereferenza. Quindi voglio respingere questo. Esempio:

#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;
}

Ho trovato e provato questo Come evitare conversioni implicite su funzioni non costruttive? come segue:

#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;
}

Ma il compilatore non mi ha ancora capito.

Qualche suggerimento?
Si prega di segnalare qualsiasi uso improprio di terminologie e ipotesi, grazie!


c'è un motivo per cui usi std::vector<const char*>invece di std::vector<std::string>>?
bolov,

Vuoi proibire nullptranche?
Jarod42

@bolov All'inizio prendo in considerazione il passaggio di questi nomi di nodi a un'interfaccia di analisi JSON, che utilizza char * in stile C come input, ma questo non è limitato qui. Ho testato, usando std :: vector <std :: string >> accetta ancora 0 durante la compilazione, ma si arresta in modo anomalo durante l'esecuzione, sulla mia macchina GCC riporta "basic_string :: _ M_construct null non valido".
Rustyhu,

@ Jarod42 Sì, quello che vuoi è letterale stringa in stile C.
Rustyhu,

Risposte:


9

Qualcosa come questo? È molto simile alla soluzione di sovraccarico che hai suggerito, ma richiede il wrapping del tipo di vettore. Non riesce a compilare se si fornisce un valore letterale 0perché viene scelto il sovraccarico del costruttore eliminato.

#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;
}

4

Con il senno di poi molte delle conversioni implicite in C ++ sono sfortunate, essendo questa una di queste.

Un'opzione da considerare è -Wzero-as-null-pointer-constantsu gcc e clang. Prestare attenzione poiché ciò modifica il comportamento dei programmi standard e, se abilitato a livello globale, può avere effetti indesiderati.

g ++ - come posso disabilitare la conversione implicita da 0 a tipi di puntatore?

Quale avviso di Clang equivale a Wzero-as-null-pointer-constant di GCC?


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.