views:

51

answers:

3

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.

A: 
obj["AA"] = "BB";

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

kafbuddy
it might make sense if the error occurred at operator[] which taken parameter of std::string reference. I still can't relate given answer to the implicit conversion-operator.
YeenFei
A: 

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.

wilx
tried but still doesn't help :(
YeenFei
+1  A: 

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.

Paul