我正在尝试创建一个“值”模板类,其中可以轻松地为其分配其他属性
属性存储在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 ==========
修改
当我从代码中删除隐式转换运算符时,它将编译而不会出错。但对我来说没有任何意义,因为到目前为止它从未使用过。
答案 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
实例的引用。