模板中的操作员错误

发布于 2024-09-25 04:40:09 字数 3941 浏览 3 评论 0原文

我正在尝试创建一个“值”模板类,可以轻松地为其分配其他属性。
属性存储在 std::map 中,并且 operator[] 已被重载以提供对它们的快速访问。

#if ! defined __VALUE_H__
#define __VALUE_H__

#include <string>
#include <map>
namespace Algorithm
{
    template<typename TValueType> 
    class CValue
    {
        public:
            CValue(const TValueType& Value) : 
            m_Value(Value)
            {
            }

            ~CValue()
            {
            }

            CValue(const CValue& Source) :
            m_Value(Source.m_Value),
            m_mssProperties(Source.m_mssProperties)
            {
            }

            CValue& operator=(const CValue& Source) 
            {
                if (this != &Source)
                {
                    m_Value = Source.m_Value;
                    m_mssProperties = Source.m_mssProperties;
                }
                return *this;
            }

            CValue& operator=(const TValueType& Source)
            {
                m_Value = Source;
                return *this;
            }

            std::string& operator[](const std::string& sPropertyName)
            {
                return m_mssProperties[sPropertyName];
            }

            std::string operator[](const std::string& sPropertyName) const
            {
                std::map<std::string, std::string>::const_iterator iter;
                iter = m_mssProperties.find(sPropertyName);
                return ((iter!=m_mssProperties.end()) ? iter->second : "");
            }

            operator TValueType () const
            {
                return m_Value;
            }

        private:
            TValueType m_Value;
            std::map<std::string, std::string> m_mssProperties;
    };
};

#endif //__VALUE_H__

为什么当我使用字符串横向调用运算符 [] 时,MSVC2008 会抱怨重载不明确。

#include <string>
#include "Value.h"

int main()
{
    std::string valName = "XX";
    std::string valProp = "YY";
    Algorithm::CValue<int>  obj(valName, 2);
    obj[valProp] = "ZZ";
    obj["AA"] = "BB";       // compiler error
    return 0;
}

编译器错误:

1>------ Build started: Project: TemplateHell, Configuration: Debug Win32 ------
1>Compiling...
1>TemplateHell.cpp
1>c:\documents and settings\yeen-fei.lim\my documents\visual studio 2008\projects\templatehell\templatehell.cpp(13) : error C2666: 'Algorithm::CValue<TValueType>::operator []' : 3 overloads have similar conversions
1>        with
1>        [
1>            TValueType=int
1>        ]
1>        c:\documents and settings\yeen-fei.lim\my documents\visual studio 2008\projects\templatehell\value.h(146): could be 'std::string Algorithm::CValue<TValueType>::operator [](const std::string &) const'
1>        with
1>        [
1>            TValueType=int
1>        ]
1>        c:\documents and settings\yeen-fei.lim\my documents\visual studio 2008\projects\templatehell\value.h(134): or       'std::string &Algorithm::CValue<TValueType>::operator [](const std::string &)'
1>        with
1>        [
1>            TValueType=int
1>        ]
1>        or       'built-in C++ operator[(int, const char [3])'
1>        while trying to match the argument list '(Algorithm::CValue<TValueType>, const char [3])'
1>        with
1>        [
1>            TValueType=int
1>        ]
1>Build log was saved at "file://c:\Documents and Settings\yeen-fei.lim\My Documents\Visual Studio 2008\Projects\TemplateHell\Debug\BuildLog.htm"
1>TemplateHell - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


编辑:

当我从代码中删除隐式转换运算符时,它将编译而不会出现错误。但这对我来说没有任何意义,因为到目前为止从未使用过它。

I am trying to create a "value" template class, where additional properties can be assign to it easily.
Properties are stored in std::map<std::string, std::string>, and operator[] has been overloaded to provide quick access to them.

#if ! defined __VALUE_H__
#define __VALUE_H__

#include <string>
#include <map>
namespace Algorithm
{
    template<typename TValueType> 
    class CValue
    {
        public:
            CValue(const TValueType& Value) : 
            m_Value(Value)
            {
            }

            ~CValue()
            {
            }

            CValue(const CValue& Source) :
            m_Value(Source.m_Value),
            m_mssProperties(Source.m_mssProperties)
            {
            }

            CValue& operator=(const CValue& Source) 
            {
                if (this != &Source)
                {
                    m_Value = Source.m_Value;
                    m_mssProperties = Source.m_mssProperties;
                }
                return *this;
            }

            CValue& operator=(const TValueType& Source)
            {
                m_Value = Source;
                return *this;
            }

            std::string& operator[](const std::string& sPropertyName)
            {
                return m_mssProperties[sPropertyName];
            }

            std::string operator[](const std::string& sPropertyName) const
            {
                std::map<std::string, std::string>::const_iterator iter;
                iter = m_mssProperties.find(sPropertyName);
                return ((iter!=m_mssProperties.end()) ? iter->second : "");
            }

            operator TValueType () const
            {
                return m_Value;
            }

        private:
            TValueType m_Value;
            std::map<std::string, std::string> m_mssProperties;
    };
};

#endif //__VALUE_H__

Why does when I invoke operator[] with string laterals, MSVC2008 complains on overloads ambiguity.

#include <string>
#include "Value.h"

int main()
{
    std::string valName = "XX";
    std::string valProp = "YY";
    Algorithm::CValue<int>  obj(valName, 2);
    obj[valProp] = "ZZ";
    obj["AA"] = "BB";       // compiler error
    return 0;
}

Compiler error:

1>------ Build started: Project: TemplateHell, Configuration: Debug Win32 ------
1>Compiling...
1>TemplateHell.cpp
1>c:\documents and settings\yeen-fei.lim\my documents\visual studio 2008\projects\templatehell\templatehell.cpp(13) : error C2666: 'Algorithm::CValue<TValueType>::operator []' : 3 overloads have similar conversions
1>        with
1>        [
1>            TValueType=int
1>        ]
1>        c:\documents and settings\yeen-fei.lim\my documents\visual studio 2008\projects\templatehell\value.h(146): could be 'std::string Algorithm::CValue<TValueType>::operator [](const std::string &) const'
1>        with
1>        [
1>            TValueType=int
1>        ]
1>        c:\documents and settings\yeen-fei.lim\my documents\visual studio 2008\projects\templatehell\value.h(134): or       'std::string &Algorithm::CValue<TValueType>::operator [](const std::string &)'
1>        with
1>        [
1>            TValueType=int
1>        ]
1>        or       'built-in C++ operator[(int, const char [3])'
1>        while trying to match the argument list '(Algorithm::CValue<TValueType>, const char [3])'
1>        with
1>        [
1>            TValueType=int
1>        ]
1>Build log was saved at "file://c:\Documents and Settings\yeen-fei.lim\My Documents\Visual Studio 2008\Projects\TemplateHell\Debug\BuildLog.htm"
1>TemplateHell - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Edit:

When i remove implicit conversion-operator from the code, it will compile without error. But it makes no sense for me because it is never used so far.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

明媚殇 2024-10-02 04:40:09

obj["AA"]...您以前见过类似的构造吗?有一个古老的 C 混淆技巧,您可以获取数组和索引并在表达式中反转它们,因为 a[b]*(a + b) 相同与b[a]相同。在这种情况下的强制转换重载中,您将返回一个整数。调用的另一个元素是字符数组。这会让编译器感到困惑,因为它不知道您是否正在尝试获取 "AA" 的元素 obj,或者您是否需要重载运算符。您可以在以下程序的输出中看到这一点:

#include <iostream>
#include <string>

using namespace std;

template <typename T>
class Val {
    T const ret;
public:
    Val(T r) : ret(r) {}

    operator T () const {
        return ret;
    }
};

int main()
{
    Val<int> v(3);
    cout << v["abcd"] << endl;
    return 0;
}

考虑以下事项:

#include <iostream>
#include <string>

using namespace std;

template <typename T>
class Val {
    T const ret;
public:
    Val(T r) : ret(r) {}

    operator T () const {
        return ret;
    }
    string operator[](string const &) const {
        return string("Hi!");
    }
};

int main()
{
    Val<int> v(3);
    cout << v["Hello!"] << endl;
    return 0;
}

这会产生类似的错误。将 Val 更改为 Val 问题就神奇地消失了(你不能用 double 索引数组;不会混淆)。

这种情况下的解决方案是创建另一个重载:string operator[](char const *) const。这样就摆脱了混乱。

obj["AA"]... have you seen a similar construct before? There is an old C obfuscation trick where you take the array and the index and reverse them in the expression as a[b] is the same as *(a + b) which is the same as b[a]. In the cast overload in this case, you are returning a integer. The other element of the call is a character array. This confuses the compiler as it doesn't know if this is you trying to get element obj of "AA", or if you want the overloaded operator. You can see this in the output of the following program:

#include <iostream>
#include <string>

using namespace std;

template <typename T>
class Val {
    T const ret;
public:
    Val(T r) : ret(r) {}

    operator T () const {
        return ret;
    }
};

int main()
{
    Val<int> v(3);
    cout << v["abcd"] << endl;
    return 0;
}

d

Consider the following:

#include <iostream>
#include <string>

using namespace std;

template <typename T>
class Val {
    T const ret;
public:
    Val(T r) : ret(r) {}

    operator T () const {
        return ret;
    }
    string operator[](string const &) const {
        return string("Hi!");
    }
};

int main()
{
    Val<int> v(3);
    cout << v["Hello!"] << endl;
    return 0;
}

This gives a similar error. Change Val<int> to Val<double> and the problem magically goes away (you can't index an array with a double; no confusion).

The solution in this case is to create another overload: string operator[](char const *) const. This gets rid of the confusion.

末骤雨初歇 2024-10-02 04:40:09
obj["AA"] = "BB";

“AA”的类型是 char* 而不是 std::string。

obj["AA"] = "BB";

"AA" is of type char* and not std::string.

只是一片海 2024-10-02 04:40:09

为什么当我调用operator[]时
弦横向,MSVC2008 抱怨
超载歧义。

因为它是暧昧的。您需要更改函数/运算符的签名。让运算符看起来像这样:

std::string& operator[](const std::string& sPropertyName);
std::string const& operator[](const std::string& sPropertyName) const;

当映射中缺少键时,不返回 "",而是返回对某个空 const std::string 实例的引用。

Why does when I invoke operator[] with
string laterals, MSVC2008 complains on
overloads ambiguity.

Because it is ambiguous. You need to change the signature of the function/operator. Make the operators look like this:

std::string& operator[](const std::string& sPropertyName);
std::string const& operator[](const std::string& sPropertyName) const;

Instead of returning "" when the key is missing in the map, return a reference to some empty const std::string instance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文