模板中的操作员错误
我正在尝试创建一个“值”模板类,可以轻松地为其分配其他属性。
属性存储在 std::map
中,并且 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__
为什么当我使用字符串横向调用运算符 [] 时,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 ==========
编辑:
当我从代码中删除隐式转换运算符时,它将编译而不会出现错误。但这对我来说没有任何意义,因为到目前为止从未使用过它。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
obj["AA"]
...您以前见过类似的构造吗?有一个古老的 C 混淆技巧,您可以获取数组和索引并在表达式中反转它们,因为a[b]
与*(a + b)
相同与b[a]
相同。在这种情况下的强制转换重载中,您将返回一个整数。调用的另一个元素是字符数组。这会让编译器感到困惑,因为它不知道您是否正在尝试获取"AA"
的元素obj
,或者您是否需要重载运算符。您可以在以下程序的输出中看到这一点:考虑以下事项:
这会产生类似的错误。将
Val
更改为Val
问题就神奇地消失了(你不能用 double 索引数组;不会混淆)。这种情况下的解决方案是创建另一个重载:
string operator[](char const *) const
。这样就摆脱了混乱。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 elementobj
of"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.“AA”的类型是 char* 而不是 std::string。
"AA" is of type char* and not std::string.
因为它是暧昧的。您需要更改函数/运算符的签名。让运算符看起来像这样:
当映射中缺少键时,不返回
""
,而是返回对某个空const std::string
实例的引用。Because it is ambiguous. You need to change the signature of the function/operator. Make the operators look like this:
Instead of returning
""
when the key is missing in the map, return a reference to some emptyconst std::string
instance.