简体   繁体   中英

std::map key not found even though the entries are identical

I'm learning C++ and I've been writing a wrapper for std::map and std::string, and I've stumbled upon a problem. Whenever I add something to the map using a string as key, once I try to access that item using the exact same key it says the key is out of bounds of the map. Here's my code (irrelevant parts left out):

ADictionary.h

#ifndef ADICTIONARY_H
#define ADICTIONARY_H

#include <map>

...

template<typename KEY, typename VALUE>
class ADictionary {
public:
    ...

    VALUE operator [](KEY key) const {
        return value.at(key);
    }

    void add(KEY key, VALUE value) {
        this->value.insert(std::make_pair(key, value));
    }

    ...

private:
    std::map<KEY, VALUE> value;
};

#endif

AString.cpp

#include "AString.h"

AString::AString() {
    value = "";
}

AString::AString(const char character) {
    value = character;
}

AString::AString(const char * characters) {
    value = characters;
}

AString::AString(std::string text) {
    value = text;
}

...

AString::operator const char *() const {
    return value.c_str();
}

AString::operator const std::string() const {
    return value;
}

...

ABoolean AString::operator<(AString & text) const {
    return getLength() < text.getLength();
}

ABoolean AString::operator>(AString & text) const {
    return text < *this;
}

ABoolean AString::operator==(AString & text) const {
    return value == text.value;
}

ABoolean AString::operator!=(AString & text) const {
    return !(text == *this);
}

AString & AString::operator=(AString & text) {
    value = text.value;

    return *this;
}

...

The code which uses the above

ADictionary<AString, AString> test;
AString a = "a";
AString b = "b";
test.add(a, b);
std::cout << test[a]; // Error occurs here, according to the program "a" is not a key in the map

I hope someone can explain to me what's going wrong. I've tried creating a dictionary with the default std::string as types and it worked correctly:

ADictionary<std::string, std::string> test;
std::string a = "a";
std::string b = "b";
test.add(a, b);
std::cout << test[a]; // No error this time

As I've said, I'm pretty new to C++ so there may be other errors. If so, feel free to point them out.

Thanks!

EDIT:

AString.h

#ifndef ASTRING_H
#define ASTRING_H

#include <string>

#include "ABoolean.h"
#include "AInteger.h"
#include "AList.h"

class ABoolean;
class AInteger;
template<typename VALUE>
class AList;

class AString {
public:
    AString();
    AString(const char);
    AString(const char *);
    AString(std::string);
    ~AString();

    operator const char *() const;
    operator const std::string() const;
    operator const AInteger() const;

    ABoolean operator<(AString &) const;
    ABoolean operator>(AString &) const;
    ABoolean operator==(AString &) const;
    ABoolean operator!=(AString &) const;
    AString & operator=(AString &);
    AString & operator+(AString &);
    AString & operator+=(AString &);

    void clear();
    ABoolean contains(AString) const;
    AInteger getIndex(AString) const;
    AInteger getLength() const;
    AList<AString> getSplit(AString) const;
    AString getSubstring(AInteger, AInteger) const;
    void removeRange(AInteger, AInteger);
    void removeSubstring(AString);
    void toLowercase();
    void toUppercase();

private:
    std::string value;
};

AString & operator+(const char, AString &);
AString & operator+(const char *, AString &);

#endif

Your string operators appear to be incorrect.

std::map uses the less than operator by default. While you provide one for AString, the only thing it does is check the length of the string. What if the two strings are of equal length?

The correct thing to do is to lexicographically compare the characters in the string. While there is a standard library function to do this, you can use operator < of the std::string values in your class:

friend bool operator<(AString const& a, AString const& b)
{
    return a.value < b.value;
}

EDIT: You may also wish to remove your conversion operators, or at least make them explicit, which prevents surprising and unwanted implicit conversions. Constructors taking one parameter (other than copy or move constructors) should also be declared explicit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM