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.
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 asa[b]is the same as*(a + b)which is the same asb[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 elementobjof"AA", or if you want the overloaded operator. You can see this in the output of the following program:Consider the following:
This gives a similar error. Change
Val<int>toVal<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.