首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多个运算符"[]“匹配这些操作数

多个运算符"[]“匹配这些操作数
EN

Stack Overflow用户
提问于 2020-02-05 02:12:24
回答 1查看 1K关注 0票数 4

我有一个类,它具有将运算符()隐式转换为内部类型的功能,并且能够通过用于设置存储的字符串索引operator[]进行访问。它在gcc 6.3和MSVC的单元测试中编译和工作得很好,但是该类会在intellisense和clang上造成一些不明确的警告,这是不可接受的。

超级瘦身版:https://onlinegdb.com/rJ-q7svG8

代码语言:javascript
复制
#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]);
        }
    }
};

用法:

代码语言:javascript
复制
    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

错误消息如下:

多个运算符"[]“匹配这些操作数:

内建运算符“整指针到对象”函数

“设置::操作员std::string key

操作数类型为:设置[ const char 15 ]

我理解错误/警告存在的原因,因为它能够用数组本身反转数组上的索引器(这本身是非常奇怪的语法,但指针算法具有逻辑意义)。

代码语言:javascript
复制
char* a = "asdf";
char b = a[5];
char c = 5[a];
b == c

我不知道如何避免它所呈现的错误信息,同时保持我想要完成的目标。(隐式赋值&字符串索引)

这有可能吗?

注意:我不能在11以上使用C++特性。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-05 02:54:26

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

代码语言:javascript
复制
template<typename T>
operator T()
{
    return data;
}

当编译器考虑表达式data["TestNode"]时,需要进行一些隐式转换。编译器有两个选项:

Setting &Setting::operator[](const std::string)

  • Convert

  • const char [9]转换为const std::string,并将Setting调用为int并调用const std::string

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

有几种方法可以绕过这件事。

备选案文1

消除从const char [9]std::string的隐式转换。您可以通过使Setting::operator[]成为接受对字符数组(对字符串文字的引用)的引用的模板来做到这一点。

代码语言:javascript
复制
template <size_t Size>
Setting &operator[](const char (&key)[Size]);

选项2

消除从Settingint的隐式转换。您可以通过将用户定义的转换标记为explicit来做到这一点。

代码语言:javascript
复制
template <typename T>
explicit operator T() const;

这将要求您更新调用代码,以使用直接初始化而不是复制初始化。

代码语言:javascript
复制
int x{data["TestNode"]};

选项3

消除从Settingint的隐式转换。另一种方法是完全删除用户定义的转换并使用函数。

代码语言:javascript
复制
template <typename T>
T get() const;

显然,这还需要您更新调用代码。

代码语言:javascript
复制
int x = data["TestNode"].get<int>();

其他一些音符

我注意到一些关于代码的事情是,您没有将用户定义的转换标记为const。如果成员函数不修改对象,则应将其标记为const,以便能够在常量对象上使用该函数。因此,将const放在参数列表之后:

代码语言:javascript
复制
template<typename T>
operator T() const {
    return data;
}

我注意到的另一件事是:

代码语言:javascript
复制
std::shared_ptr<Setting>(new Setting())

在这里,您将提到两次Setting,并在可能执行的情况下执行两次内存分配。对于代码的清洁度和性能来说,最好这样做:

代码语言:javascript
复制
std::make_shared<Setting>()

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

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60068103

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档