Cómo evitar conversiones implícitas de int (0) a puntero en un vector

9

Hay una situación en la que quiero recopilar todos los nombres de nodos de una ruta a una clave en JSON. Tenga en cuenta la condición del índice de matriz "0", "1" también están permitidos, pero es fácil olvidar las comillas, lo que provocaría un bloqueo cuando se desreferenciara. Entonces quiero rechazar esto. Ejemplo:

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

Encontré y probé esto ¿Cómo evito las conversiones implícitas en funciones que no son de construcción? de la siguiente manera:

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

Pero el compilador todavía no me entendió.

¿Cualquier sugerencia?
Señale cualquier mal uso de terminologías y suposiciones, ¡gracias!

rustyhu
fuente
¿hay alguna razón por la que usas en std::vector<const char*>lugar de std::vector<std::string>>?
bolov
¿Quieres prohibir nullptrtambién?
Jarod42
@bolov Al principio, considero pasar estos nombres de nodos a una interfaz de análisis JSON, que usa char * de estilo C como entrada, pero esto no está limitado aquí. He probado, usando std :: vector <std :: string >> todavía acepta 0 cuando se compila, pero se bloquea cuando se ejecuta, en mi máquina GCC informa "basic_string :: _ M_construct null not valid".
rustyhu
@ Jarod42 Sí, lo que quiero es literal de cadena de estilo C.
rustyhu

Respuestas:

9

¿Algo como esto? Es muy similar a la solución de sobrecarga que sugirió, pero requiere ajustar el tipo de vector. No se genera si proporciona un literal 0porque se elige la sobrecarga del constructor eliminado.

#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
fuente
4

En retrospectiva, muchas de las conversiones implícitas en C ++ son desafortunadas, siendo esta una de ellas.

Una opción a considerar es -Wzero-as-null-pointer-constanten gcc y clang. Tenga cuidado ya que esto cambia el comportamiento de los programas estándar y, si está habilitado a nivel mundial, puede tener algunos efectos no deseados.

g ++: ¿cómo desactivo la conversión implícita de 0 a tipos de puntero?

¿Qué advertencia de Clang es equivalente a Wzero-as-null-pointer-constant de GCC?

bolov
fuente