1

Tried to argument the std::string so that it supports method "bool operator==(int)". I got errors:

$ g++ -std=c++11 te2.cc
te2.cc: In function ‘int main(int, char**)’:
te2.cc:20:20: error: no matching function for call to ‘mstring::mstring(const char [4])’
te2.cc:20:20: note: candidates are:
te2.cc:10:7: note: mstring::mstring()
te2.cc:10:7: note:   candidate expects 0 arguments, 1 provided
te2.cc:10:7: note: mstring::mstring(const mstring&)
te2.cc:10:7: note:   no known conversion for argument 1 from ‘const char [4]’ to ‘const mstring&’
te2.cc:10:7: note: mstring::mstring(mstring&&)
te2.cc:10:7: note:   no known conversion for argument 1 from ‘const char [4]’ to ‘mstring&&’

Here is the simple source:

#include <unordered_map>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <iostream>

using namespace std;


class mstring : public string {
public:
    //mstring (char* p) : std::string(p) {};
    bool operator == (int x) {
        int n = atoi(this->c_str());
        return (n == x);
    }
};

int main(int argc, char *argv[])
{
    mstring t("123");
    if (t == atoi(argv[1])) {
        printf("yes\n");
    } else {
        printf("no\n");
    }
}

If I uncomment the constructor /mstring (char* p) : std::string(p) {};, then it compiles and runs fine.

The question is, if it possible to make it work without defining the constructors for mstring, just use the whatever the constructors of the base class (there is no new data member anyway)? Thanks.

packetie
  • 4,839
  • 8
  • 37
  • 72
  • 5
    Usually inheriting classes from the `std` namespace is a pretty bad idea. – πάντα ῥεῖ May 16 '15 at 23:45
  • You can define `operator==(const std::string&, int)` as a standalone, non-member function, if you are so inclined. In fact, you likely want it this way - you probably also want a symmetrical `operator==(int, const std::string&)`, which can't be a member function anyhow. – Igor Tandetnik May 16 '15 at 23:46
  • 2
    You don't need to convert argv[1] to int. Compare it directly to a std::string. – Cheers and hth. - Alf May 16 '15 at 23:49

2 Answers2

5

What about providing a free standing operator function instead of inheriting from std::string (which makes that code more usable overall):

bool operator==(const std::string& s, int i) {
    int n = atoi(s.c_str());
    return (n == i);
}

bool operator==(int i, const std::string& s) {
    return s == i;
}

Or even more generic:

template<typename T>
bool operator==(const std::string& s, T t) {
    std::istringstream iss;
    iss << t;
    return (s == iss.str());
}

Classes from the std namespace aren't intended to be inherited, but just used in interfaces and function parameters. Inheriting from those classes makes your code less usable, since clients need to use your implementation instead of just using the std type.


Also note: For your particular use case it's not necessary to convert anything at all, unless you want to assert that argv[1] contains a number (where atoi() certainly isn't the best method to do so, look up stoi() instead). You can just compare the strings:

if (std::string("123") == argv[1]) {
    printf("yes\n");
} else {
    printf("no\n");
}
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • That's the perfect solution. Seen it before but it didn't occur to me until I see your solution. Thanks. – packetie May 17 '15 at 01:13
2

you can explicitly inherit the constructors by adding

using string::string;

in your class

sp2danny
  • 7,488
  • 3
  • 31
  • 53