2010-09-30 16 views
1

J'essaye de créer une classe de gabarit "value", où des propriétés additionnelles peuvent être assignées facilement.
Les propriétés sont stockées dans std::map<std::string, std::string> et operator[] a été surchargé pour permettre un accès rapide à celles-ci.Erreur d'opérateur dans le gabarit

#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__ 

Pourquoi est-ce que j'invoque l'opérateur [] avec laterals chaîne, MSVC2008 se plaint sur l'ambiguïté Surcharges.

#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; 
} 

erreur du compilateur:

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:

Quand je supprime la conversion-opérateur implicite à partir du code, il compilera sans erreur. Mais cela n'a pas de sens pour moi parce qu'il n'est jamais utilisé jusqu'ici. "AA" est de type char * et non de std :: string

Répondre

2

obj["AA"] ... avez-vous déjà vu une construction similaire? Il y a un vieux truc de C obfuscation où vous prenez le tableau et l'index et inversez-les dans l'expression comme a[b] est le même que *(a + b) qui est le même que b[a]. Dans la casse, dans ce cas, vous renvoyez un entier. L'autre élément de l'appel est un tableau de caractères. Cela complique le compilateur car il ne sait pas si vous essayez d'obtenir l'élément obj de "AA", ou si vous voulez l'opérateur surchargé. Vous pouvez le voir dans la sortie du programme suivant:

#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

Considérez ce qui suit:

#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; 
} 

Cela donne une erreur semblable. Changez Val<int> en Val<double> et le problème disparaît comme par magie (vous ne pouvez pas indexer un tableau avec un double, pas de confusion). La solution dans ce cas est de créer une autre surcharge: string operator[](char const *) const. Cela élimine la confusion.

0
obj["AA"] = "BB"; 

+0

cela peut être logique si l'erreur est survenue à l'opérateur [] qui a pris le paramètre de la référence std :: string. Je ne peux toujours pas relier la réponse donnée à l'opérateur de conversion implicite. – YeenFei

0

Why does when I invoke operator[] with string laterals, MSVC2008 complains on overloads ambiguity.

Parce qu'il est ambigu. Vous devez changer la signature de la fonction/opérateur. Faire les opérateurs se présentent comme suit:

std::string& operator[](const std::string& sPropertyName); 
std::string const& operator[](const std::string& sPropertyName) const; 

au lieu de retourner "" lorsque la clé est manquante sur la carte, retourner une référence à une const std::string instance vide.

+0

essayé mais n'aide pas :( – YeenFei