如何避免从整数 0 到指针的隐式转换,作为向量的元素

How to avoid implicit conversions from integer 0 to pointer, as the element of a vector

有一种情况,我想收集JSON中一个键的路径的所有节点名称。考虑条件: JSON 数组索引“0”、“1”也是允许的,但是很容易忘记引号,在解引用时会导致崩溃。所以我希望编译器拒绝这种参数。示例:

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

参考 How do I avoid implicit conversions on non-constructing functions? 我尝试了以下操作:

#include <vector>
#include <iostream>

// I want to describe only char pointer parameter is allowed as element,
// parameter of any integer types should be rejected.
int func(const std::vector<const char*>& pin) {
    return pin.size();
}

int func(const std::vector<int>& pin) = delete;
// or
template<typename T>
int func(const std::vector<T>& pin) = delete;

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

但是编译器还是不能理解我
有什么建议吗?

请指出任何对术语和假设的误用,谢谢!

是这样的吗?它与您建议的重载解决方案非常相似,但需要包装矢量类型。如果您提供文字 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;
}

事后看来,C++ 中的许多隐式转换都是不幸的,这就是其中之一。

要考虑的一个选项是 -Wzero-as-null-pointer-constant gcc 和 clang。请小心,因为这会改变标准程序的行为,如果全局启用可能会产生一些意想不到的效果。

g++ - how do I disable implicit conversion from 0 to pointer types?

我喜欢. However there already exists a solution in Guideline Support Library:

gsl::not_null

我强烈推荐 GSL。它由许多 C++ 专家创建和支持,其中包括 Bjarne Stroustrup 本人和 Herb Sutter。 C++ Core Guidelines 正在积极集成到编译器警告和静态分析器中。