Ошибка оператора в шаблоне - PullRequest
       20

Ошибка оператора в шаблоне

1 голос
/ 30 сентября 2010

Я пытаюсь создать шаблонный класс "value", в котором ему могут быть легко назначены дополнительные свойства.
Свойства хранятся в 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__

Почему, когда я вызываю 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 ==========


Edit:

Когда я удаляю неявный оператор преобразования из кода, он будет компилироваться без ошибок. Но для меня это не имеет смысла, потому что до сих пор его не использовали.

Ответы [ 3 ]

2 голосов
/ 30 сентября 2010

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,Это избавляет от путаницы.

0 голосов
/ 30 сентября 2010

Почему, когда я вызываю оператор [] с боковые строки, MSVC2008 жалуется на перегружает двусмысленность.

Потому что это неоднозначно. Вам необходимо изменить подпись функции / оператора. Сделайте так, чтобы операторы выглядели так:

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

Вместо того, чтобы возвращать "", когда ключ отсутствует на карте, вернуть ссылку на некоторый пустой const std::string экземпляр.

0 голосов
/ 30 сентября 2010
obj["AA"] = "BB";

"AA" имеет тип char *, а не std :: string.

...