模板中的操作员错误

时间:2010-09-30 05:13:03

标签: c++ templates operator-overloading compiler-errors

我正在尝试创建一个“值”模板类,其中可以轻松地为其分配其他属性 属性存储在std::map<std::string, std::string>中,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__

为什么当我用字符串laterals调用operator []时,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 ==========


修改

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

3 个答案:

答案 0 :(得分:2)

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

#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

请考虑以下事项:

#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<int>更改为Val<double>,问题会神奇地消失(您无法使用双精度索引数组;不会产生混淆)。

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

答案 1 :(得分:0)

obj["AA"] = "BB";

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

答案 2 :(得分:0)

  

为什么当我调用operator []时   字符串laterals,MSVC2008抱怨   超载歧义。

因为它含糊不清。您需要更改函数/运算符的签名。让运算符看起来像这样:

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

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