开发者

Operator error in template

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 settin开发者_运维知识库gs\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.


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.


obj["AA"] = "BB";

"AA" is of type char* and not 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜