packetie
packetie

Reputation: 5059

skipping adding constructors when inheriting from std::string class

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.

Upvotes: 1

Views: 97

Answers (2)

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

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");
}

Upvotes: 5

sp2danny
sp2danny

Reputation: 7646

you can explicitly inherit the constructors by adding

using string::string;

in your class

Upvotes: 2

Related Questions