8

Is there a (more or less at least) standard int class for c++?

If not so, is it planned for say C++13 and if not so, is there any special reasons?

OOP design would benefit from it I guess, like for example it would be nice to have an assignment operator in a custom class that returns an int:

int i=myclass;

and not

int i=myclass.getInt();

OK, there are a lot of examples where it could be useful, why doesn't it exist (if it doesn't)?

It is for dead reckoning and other lag-compensating schemes and treating those values as 'normal' variables will be nice, hopefully anyway!.

Vertexwahn
  • 6,759
  • 6
  • 50
  • 78
Valmond
  • 2,640
  • 8
  • 25
  • 45
  • 17
    Nothing planned, and the reason is that C++ is not a certain language that shoehorns everything into objects. – Xeo Mar 06 '12 at 16:01
  • If there are so many examples I would like to read some. Also: What is the mechanism you want to achieve in your example? Is the first better than the second just because it is shorter? I think the second one visualizes its purpose much better than the first. – Nobody moving away from SE Mar 06 '12 at 16:02
  • 8
    What’s wrong with plain `int`?! – Konrad Rudolph Mar 06 '12 at 16:02
  • 3
    What specifically are you looking for that `int` does not provide? – tenfour Mar 06 '12 at 16:06
  • Performing that assignment for the sake of it seems not very useful, so my guess is that you intend on doing something else with your *objectized* `int`? What would you gain from having an `int` *class*? What is it that you miss? – David Rodríguez - dribeas Mar 06 '12 at 16:08
  • Thanks for all answers and I'm happy to see that you Can do what I wanted (It is for dead reckoning and other lag-compensating schemes). – Valmond Mar 06 '12 at 16:08
  • @Xeo, careful of the terms, all data is actually an `object` but not a `class` type. – edA-qa mort-ora-y Mar 06 '12 at 16:10
  • OOP design wouldn't benefit from it, because C++ has no type comparable to (say) `java.lang.Object`, which is a common base for all classes (or "evil overclass"). Any operations in C++ that can be performed on an object of unknown class type, can also be performed on an object of type `int`. So there's no use for a class, and not really any important difference in C++ between classes and other types, except that the builtin types come with a bunch of builtin operators and conversions. Just use the type `int`. – Steve Jessop Mar 06 '12 at 16:10
  • @edA: Yeah, I should've said "into object oriented design", but oh well. – Xeo Mar 06 '12 at 16:14
  • To reiterate what @Nobody said: What would be the good examples for why an `Integer`-class would be beneficial? After having done C# professionally for several years, I can't remember a case where there wasn't an equal/better solution in C++ already. – Sebastian Mach Mar 06 '12 at 16:46
  • @eda Evaluating a scalar prvalue yields a *value*, not an object. – fredoverflow Mar 06 '12 at 17:26
  • @FredOverflow, no, I mean all data in C++ (and C) is called "objects". That's just how the standard defines it. Check out _1.8 The C++ Object Model_ in the standard. – edA-qa mort-ora-y Mar 06 '12 at 18:33
  • @phresnel: Added type safety. I've had cases where I had to increase the size of an ID type; the best way to safely do this was using a wrapped integer to prevent promotion/demotion. – Collin Dauphinee Mar 06 '12 at 20:54
  • @dauphic: Seems like a valid case for a safe integer that checks for overflow et al, or an Id class in the first place; imo unrelated to int-classes design-wise. There is no generic concept for identifiers, git for example has a kind of GUID. Anyways, I think codeplex has a relatively popular example of a safe integer, tho the code is imho horrible. – Sebastian Mach Mar 06 '12 at 21:44
  • 2
    @eda An int variable is an object, but 42 is *not* an object. – fredoverflow Mar 07 '12 at 01:44
  • Fortunately, when you use the literal `42` as, say, the argument expression to a function that takes a `const int&` parameter, then the implementation creates an `int` object for you with value 42. So in such cases, where you need an object, you get one just as you would if you explicitly created a temporary of class type, `Int(42)`. – Steve Jessop Mar 07 '12 at 09:46

11 Answers11

20

it would be nice to have an assignment operator in a custom class that returns an int

You can do that with a conversion operator:

class myclass {
    int i;
public:
    myclass() : i(42) {}

    // Allows implicit conversion to "int".
    operator int() {return i;}
};

myclass m;
int i = m;

You should usually avoid this, as the extra implicit conversions can introduce ambiguities, or hide category errors that would otherwise be caught by the type system. In C++11, you can prevent implicit conversion by declaring the operator explicit; then the class can be used to initialise the target type, but won't be converted implicitly:

int i(m);    // OK, explicit conversion
i = m;       // Error, implicit conversion
Mike Seymour
  • 235,407
  • 25
  • 414
  • 617
  • 6
    You must think twice when you want to use the conversion operators, because they make your code less obvious – Alecs Mar 06 '12 at 16:04
  • 2
    @Alecs: The OP must think thrice atleast why he wants such *semantics*. – Xeo Mar 06 '12 at 16:08
  • I think I have a valid use case for this behaviour. I want to have a wrapper class for `int` which notifies a Java object (via JNI) of any changes in its value. By using conversion operators, I am able to overload assignment/modification operators (`=`, `++`, `--`) to notify the Java object, without breaking the functionality of existing references to the object as an int. Without being able to extend `int` as it is a primitive data type and not a class, this seems to be a good solution. Am I missing something, or is this a good solution to my problem? – StockB Jan 23 '13 at 17:31
5

If you want to allow your class to implicitly convert to int, you can use an implicit conversion operator (operator int()), but generally speaking implicit conversions cause more problems and debugging than they solve in ease of use.

Mark B
  • 91,641
  • 10
  • 102
  • 179
3

If your class models an int, then the conversion operator solution presented by other answers is fine, I guess. However, what does your myclass model?

What does it mean to get an integer out of it?

That's what you should be thinking about, and then you should come to the conclusion that it's most likely meaningless to get an integer without any information what it represents.

Take std::vector<T>::size() as an example. It returns an integer. Should std::vector<T> be convertible to an integer for that reason? I don't think so. Should the method be called getInt()? Again, I don't think so. What do you expect from a method called getInt()? From the name alone, you learn nothing about what it returns. Also, it's not the only method that returns an integer, there's capacity() too.

Xeo
  • 123,374
  • 44
  • 277
  • 381
2

Implement operator int () for your class

knivil
  • 898
  • 5
  • 10
1

There are obvious reasons to have a class for int, because int by itself does not allow for the absence of any value. Take for instance a JSON message. It can contain the definition for an object named “foo”, and an integer named “bar”, for example:

{"foo": {"bar": 0}}

Which has the meaning that “bar" is equal to 0 (zero), but if you omit “bar”, like this:

{"foo": {}}

Now it takes on the meaning that “bar” is non-existent, which is a completely different meaning and cannot be represented by int alone. In the old days, if this situation arose, some programmers would use a separate flag, or use a specific integer value to signify that the value was not supplied, or undefined, or non-existent. But whatever you call it, a better way is to have a class for integer which defines the functionality and makes it reusable and consistent.

Another case would be a database table that has an integer column added some time after it’s creation. Records that were added prior to when the new column was added will return null, meaning no value present, and records added after the column’s creation would return a value. You may need to take a different action for null value vs. 0 (zero).

So here's the beginnings of what a class for int or string might look like. But before we get to the code, let's look at the usage as that is why you would create the class in the first place, to make your life easier in the long run.

int main(int argc, char **argv) {

    xString name;
    xInt    age;

    std::cout<< "before assignment:" << std::endl;
    std::cout<< "name is " << name << std::endl;
    std::cout<< "age is " << age << std::endl;

    // some data collection/transfer occurs
    age  = 32;
    name = "john";

    // data validation
    if (name.isNull()) {
        throw std::runtime_error("name was not supplied");
    } 

    if (age.isNull()) {
        throw std::runtime_error("age was not supplied");
    }

    // data output
    std::cout<< std::endl;
    std::cout<< "after assignment:" << std::endl;
    std::cout<< "name is " << name << std::endl;
    std::cout<< "age is " << age << std::endl;

    return 0;
}

Here is the sample output from the program:

before assignment:
name is null
age is null

after assignment:
name is john
age is 32

Note that when the instance of the xInt class has not been assigned a value, the << operator automatically prints "null" instead of zero, and the same applies to xString for name. What you do here is totally up to you. For instance, you might decide to print nothing instead of printing “null”. Also, for the sake of brevity, I've hard coded the assignments. In the real world, you would be gathering/parsing data from a file or client connection, where that process would either set (or not set) the data values according to what is found in the input data. And of course, this program won't actually ever throw the runtime exceptions, but I put them there to give you a flavor of how you might throw the errors. So, one might say, well, why don't you just throw the exception in your data collection process? Well, the answer to that is, with the eXtended class variables (xInt & xString), we can write a generic, reusable, data gathering process and then just examine the data that is returned in our business logic where we can then throw appropriate errors based on what we find.

Ok, so here's the class code to go with the above main method:

#include <iostream>
#include <string>


class xInt {
private:
    int  _value=0;
    bool _isNull=true;

public:
    xInt(){}
    xInt(int value) {
        _value=value; 
        _isNull=false;
    }

    bool isNull(){return _isNull;}
    int  value() {return _value;}
    void unset() {
        _value=0;
        _isNull=true;
    }

    friend std::ostream& operator<<(std::ostream& os, const xInt& i) {
        if (i._isNull) {
            os << "null";
        } else {
            os << i._value;
        }
        return os;
    }

    xInt& operator=(int value) {
        _value=value;
        _isNull=false;
        return *this;
    }
    operator const int() {
        return _value;
    }
};

class xString {
private:
    std::string _value;
    bool   _isNull=true;

public:
    xString(){}
    xString(int value) {
        _value=value; 
        _isNull=false;
    }

    bool   isNull() {return _isNull;}
    std::string value()  {return _value;}
    void   unset()  {
        _value.clear();
        _isNull=true;
    }


    friend std::ostream& operator<<(std::ostream& os, const xString& str) {
        if (str._isNull) {
            os << "null";
        } else {
            os << str._value;
        }
        return os;
    }

    xString& operator<<(std::ostream& os) {
        os << _value;
        return *this;
    }

    xString& operator=(std::string value) {
        _value.assign(value);
        _isNull=false;
        return *this;
    }
    operator const std::string() {
        return _value;
    }
};

Some might say, wow, that's pretty ugly compared to just saying int or string, and yes, I agree that it's pretty wordy, but remember, you only write the base class once, and then from then on, your code that you're reading and writing every day would look more like the main method that we first looked at, and that is very concise and to the point, agreed? Next you'll want to learn how to build shared libraries so you can put all these generic classes and functionality into a re-usable .dll or .so so that you're only compiling the business logic, not the entire universe. :)

wryan
  • 991
  • 7
  • 4
1

This can be realized by the cast operator. E.g:

class MyClass {
private:
    int someint;
public:
    operator const int() {
        return this->someint;
    }
}
Constantinius
  • 30,633
  • 7
  • 68
  • 82
1

No there isn't any standard int class. For things such as BigDecimal you can look at Is there a C++ equivalent to Java's BigDecimal?

As for int, if you really need it, you can create your own. I have never come across an instance where I needed an Integer class.

Community
  • 1
  • 1
Sid
  • 7,125
  • 1
  • 25
  • 40
1

No, and there won't be any. What you want to do can be done with conversion operator:

#include <iostream>

struct foo {
    int x;
    foo(int x) : x(x) {}
    operator int() { return x; }
};

int main() {
    foo x(42);
    int y(x);
    std::cout << y;
}
Cat Plus Plus
  • 113,388
  • 26
  • 185
  • 215
  • @sbi: That depends. If you are writing a type for restricted integer ranges, implicit conversion to int is exactly the right thing to do. Of course you *very* rarely do that. – celtschk Mar 06 '12 at 22:37
  • @celtschk: I once thought that, too. But I have been bitten by this too often. Every single one of the few implicit conversions I have written which are part of codebases still in use got removed over the years because they caused trouble. – sbi Mar 09 '12 at 09:04
  • @sbi: Then maybe you had problems with *inappropriate* implicit conversions (note that many of the standard implicit conversions in C++ are wrong in my opinion). Note especially that my example is a *restricted* int class, something which few people dare to implement (just using an int is much simpler). An implicit conversion from an *extended* integer class ("bigint") to int is clearly wrong. – celtschk Mar 09 '12 at 21:16
  • @celtschk: If those were inappropriate (well, IMO they certainly were, because we had too remove them), then I have, in almost 20 years of writing C++ code, not come across a single case of implicit conversions being appropriate. All the cases I have seen sooner or later were found to be the culprit for some very hard to diagnose errors, caused by implicit conversions implicitly kicking in. (This does include a `Byte` class, BTW.) – sbi Mar 09 '12 at 23:55
  • Was it implicit conversion from `Byte` to `int` (IMHO appropriate) or conversion from `int` to `Byte` (IMHO inappropriate) which turned out problematic? – celtschk Mar 10 '12 at 07:27
1

No, and there probably won't be.

int i=myclass;

This is covered by conversion operators:

struct MyClass {
    operator int() {
        return v;
    }
    int v;
} myclass = {2};
int i = myclass; // i = 2

Not everything has to be 'object oriented'. C++ offers other options.

bames53
  • 79,748
  • 13
  • 162
  • 229
0

Your cast operator should realize this

An example

class MyClass {
private:
    int someint;
public:
    operator const int() {
        return this->someint;
    }
}
0

There's no reason to have one, and so there won't be any.

Puppy
  • 138,897
  • 33
  • 232
  • 446
  • 1
    Please see my comment to Mike Seymour. – StockB Jan 23 '13 at 17:28
  • Looks like it's technically possible (correct me please) to convert C++ type-system to have only objects. If we pretend that `int` is a final class with overloaded operators with built-in support for literals. So 5 creates an object of class `int`. Why would you want to do that? Well, if, C++ also adds a couple of methods like `repeat` you would be able to write something like `5.repeat([]{ your_code; });` Aren't there only a few backward compatibility problems such as type_traits and ... ? – sasha.sochka Feb 07 '14 at 22:05
  • You would also be able to write `repeat(5, []{ your code; });` right now. Even the C++ committee aren't sufficiently insane to make `int` into a class. The C++ type system is already composed of only objects (except references). There's no reason to change the existing primitives, which are already objects. – Puppy Jul 04 '14 at 09:01