gpt4 book ai didi

c++ - 多个运算符 "[]"匹配这些操作数

转载 作者:行者123 更新时间:2023-12-01 14:20:24 26 4
gpt4 key购买 nike

我有一个类,它具有到内部类型的隐式转换 operator() 和用于设置存储的字符串索引 operator[] 访问的能力。它在 gcc 6.3 和 MSVC 上的单元测试中编译并运行良好,但是该类在智能感知和 clang 上导致一些不明确的警告,这是 Not Acceptable 。
super 瘦身版:
https://onlinegdb.com/rJ-q7svG8

#include <memory>
#include <unordered_map>
#include <string>


struct Setting
{
int data; // this in reality is a Variant of intrinsic types + std::string
std::unordered_map<std::string, std::shared_ptr<Setting>> children;
template<typename T>
operator T()
{
return data;
}
template<typename T>
Setting & operator=(T val)
{
data = val;
return *this;
}
Setting & operator[](const std::string key)
{
if(children.count(key))
return *(children[key]);
else
{
children[key] = std::shared_ptr<Setting>(new Setting());
return *(children[key]);
}
}
};

用法:
    Setting data;
data["TestNode"] = 4;
data["TestNode"]["SubValue"] = 55;
int x = data["TestNode"];
int y = data["TestNode"]["SubValue"];
std::cout << x <<std::endl;
std::cout << y;

output:
4
55
错误信息如下:

more than one operator "[]" matches these operands:

built-in operator "integer[pointer-to-object]" function

"Setting::operator[](std::string key)"

operand types are: Setting [ const char [15] ]


我理解为什么会出现错误/警告,因为它可以用数组本身反转数组上的索引器(这本身就是非常奇怪的语法,但在逻辑上对指针算术有意义)。
char* a = "asdf";
char b = a[5];
char c = 5[a];
b == c

我不确定如何在保持我想要完成的任务的同时避免它显示的错误消息。 (隐式赋值和字符串索引)
那可能吗?
注意:我不能使用 11 以上的 C++ 特性。

最佳答案

问题是用户定义的隐式转换函数模板。

template<typename T>
operator T()
{
return data;
}

当编译器考虑表达式 data["TestNode"] ,需要进行一些隐式转换。编译器有两个选项:
  • 转换 const char [9]const std::string并调用 Setting &Setting::operator[](const std::string)
  • 转换 Settingint并调用 const char *operator[](int, const char *)

  • 这两个选项都涉及隐式转换,因此编译器无法决定哪个更好。编译器说这个调用是不明确的。

    有几种方法可以解决这个问题。

    选项1

    const char [9] 消除隐式转换至 std::string .您可以通过制作 Setting::operator[] 来做到这一点。接受对字符数组的引用(对字符串文字的引用)的模板。
    template <size_t Size>
    Setting &operator[](const char (&key)[Size]);

    选项 2

    Setting 消除隐式转换至 int .您可以通过将用户定义的转换标记为 explicit 来做到这一点。 .
    template <typename T>
    explicit operator T() const;

    这将要求您更新调用代码以使用直接初始化而不是复制初始化。
    int x{data["TestNode"]};

    选项 3

    Setting 消除隐式转换至 int .另一种方法是完全删除用户定义的转换并使用函数。
    template <typename T>
    T get() const;

    显然,这也需要您更新调用代码。
    int x = data["TestNode"].get<int>();

    其他一些注意事项

    我注意到关于代码的一些事情是你没有将用户定义的转换标记为 const .如果成员函数不修改对象,则应将其标记为 const能够在常量对象上使用该函数。所以把 const在参数列表之后:
    template<typename T>
    operator T() const {
    return data;
    }

    我注意到的另一件事是:
    std::shared_ptr<Setting>(new Setting())

    你在这里提到 Setting两次并在您可以做一次内存分配时进行两次内存分配。为了代码清洁和性能,最好这样做:
    std::make_shared<Setting>()

    还有一件事,我不太了解你的设计,无法自己做出这个决定,但你真的需要使用 std::shared_ptr ?我不记得上次使用 std::shared_ptr 是什么时候了如 std::unique_ptr效率更高,在大多数情况下似乎就足够了。真的,你真的需要一个指针吗?是否有任何理由使用 std::shared_ptr<Setting>std::unique_ptr<Setting>Setting ?只是想一想。

    关于c++ - 多个运算符 "[]"匹配这些操作数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60068103/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com