【问题标题】:How to avoid implicit conversions from integer 0 to pointer, as the element of a vector如何避免从整数 0 到指针的隐式转换,作为向量的元素
【发布时间】:2020-04-16 05:19:02
【问题描述】:

有一种情况,我想收集 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;
}

但编译器仍然无法理解我。
有什么建议吗?

请指出任何滥用术语和假设的地方,谢谢!

【问题讨论】:

  • 你使用std::vector&lt;const char*&gt;而不是std::vector&lt;std::string&gt;&gt;有什么原因吗?
  • 你也要禁止nullptr吗?
  • @bolov 一开始我考虑将这些节点名称传递给 JSON 分析接口,该接口使用 C 风格的 char* 作为输入,但这里不限于此。我已经测试过,使用 std::vector<:string>> 在编译时仍然接受 0,但在运行时崩溃,在我的机器上 GCC 报告“basic_string::_M_construct null not valid”。
  • @Jarod42 是的,需要的是 C 风格的字符串文字。

标签: c++ implicit-conversion function-parameter


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

    Which Clang warning is equivalent to Wzero-as-null-pointer-constant from GCC?

    【讨论】:

      【解决方案3】:

      我喜欢Mikel Rychliski's answer。不过Guideline Support Library已经有解决方案了:

      gsl::not_null

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-23
        • 1970-01-01
        • 1970-01-01
        • 2019-06-18
        • 1970-01-01
        • 1970-01-01
        • 2022-01-18
        • 2016-12-26
        相关资源
        最近更新 更多