多个运算符“ []”与这些操作数匹配

克里普托

我有一个类,它既具有对内在类型的隐式转换operator(),又具有通过用于设置存储的字符串索引operator []进行访问的能力。它在gcc 6.3和MSVC的单元测试中可以编译并很好地工作,但是该类在intellisense和clang上引起了一些歧义性警告,这是不可接受的。

超级瘦身版: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

错误信息如下:

多个运算符“ []”与以下操作数匹配:

内置运算符“整数[指针到对象]”功能

“ Setting :: operator [](std :: string键)”

操作数类型为:设置[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_ptrstd::unique_ptr是更有效,似乎是足够在大多数情况下。确实,您是否完全需要一个指针?是否有使用std::shared_ptr<Setting>std::unique_ptr<Setting>结束的理由Setting只是要考虑的事情。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

没有运算符“ ==”使这些操作数匹配

没有运算符“/”匹配这些操作数

“没有运算符 >> 匹配这些操作数”

没有与这些操作数匹配的运算符“ <”,操作数类型为:double <my_class

没有运算符“>>”匹配这些操作数操作数类型是:std::istream>>int

没有运算符“ >>”与这些操作数匹配-操作数类型为:std :: istream >> const double

没有运算符“>>”匹配这些操作数操作数类型是:std::istream >> double*

没有运算符匹配这些操作数;操作数类型为:std::istream >> const char [5]

C++ 没有运算符 [] 匹配这些操作数

E0349 没有运算符“>>”匹配这些操作数

错误:没有运算符“ <”与这些操作数匹配

IntelliSense:没有运算符“ <<”与这些操作数匹配

C ++-没有运算符“ <<”与这些操作数匹配directory_iterator()

错误:没有运算符“==”匹配这些操作数

C ++)E0349没有运算符匹配这些操作数

C ++-错误-没有运算符“ []”与这些操作数匹配

没有运算符“ <<”与这些操作数匹配-C ++

没有运算符“” <<“”匹配这些操作数错误

错误:没有运算符“!=”与这些操作数匹配

没有运算符“=”匹配这些操作数错误

在执行operator >>时出错:C ++没有运算符与这些操作数匹配,操作数类型为:std :: istream >> const double error

运算符重载多个操作数C ++

使用 while 循环时,没有运算符 ">=" 匹配 C++ 中的这些操作数错误

访问std :: map中的条目会导致“没有运算符“ []”与这些操作数匹配”

使用 while 循环时,没有运算符 ">=" 匹配 C++ 中的这些操作数错误

没有运算符“+”匹配这些操作数,也就是不能将 Array<double> 添加到 double

没有运算符“ =”与这些操作数匹配。我已经超载了,但似乎无法正常工作

我正在尝试使用 cout,我收到此消息,没有运算符“>>”与这些操作数匹配

没有运算符“<<”匹配对象和字符串文字之间的这些操作数错误