Как избежать неявных преобразований из целого числа 0 в указатель, как элемент вектора - PullRequest
9 голосов
/ 16 апреля 2020

Есть ситуация, когда я хочу собрать все имена узлов пути к ключу в JSON. Рассмотрим условие индекса массива «0», «1» также допускается, но легко забыть кавычки, что привело бы к cra sh при разыменовании. Поэтому я хочу отказаться от этого. Пример:

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

Я нашел и попробовал это Как избежать неявных преобразований для не конструирующих функций? следующим образом:

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

Но компилятор все еще не понял меня.

Любое предложение?
Пожалуйста, укажите на любое неправильное использование терминологии и предположений, спасибо!

Ответы [ 3 ]

10 голосов
/ 16 апреля 2020

Как то так? Это очень похоже на решение по перегрузке, которое вы предложили, но требует переноса векторного типа. Не в состоянии строить, если вы предоставляете литерал 0, потому что выбрана перегрузка удаленного конструктора.

#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 голосов
/ 16 апреля 2020

Оглядываясь назад, многие из неявных преобразований в C ++ неудачны, и это один из них.

Один из вариантов для рассмотрения - -Wzero-as-null-pointer-constant на g cc и лязг. Будьте осторожны, так как это меняет поведение стандартных программ и, если оно включено глобально, может привести к непредвиденным последствиям.

g ++ - как отключить неявное преобразование из 0 в типы указателей?

Какое предупреждение Clang эквивалентно константе Wzero-as-null-pointer из G CC?

3 голосов
/ 16 апреля 2020

Мне нравится Ответ Микеля Ричлиски . Однако в Guideline Support Library уже существует решение :

gsl::not_null

Я настоятельно рекомендую GSL. Он создан и поддерживается многими экспертами C ++, в том числе Бьярном Страуструпом и Хербом Саттером. И C ++ Core Guidelines активно интегрируется в предупреждения компилятора и анализаторы состояния c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...