Gusev Slava
Gusev Slava

Reputation: 2204

C++: Create integer vector of infinities

I'm working on an algorithm and I need to initialize the vector of ints:

std::vector<int> subs(10)

of fixed length with values:

{-inf, +inf, +inf …. }

This is where I read that it is possible to use MAX_INT, but it's not quiete correct because the elements of my vector are supposed to be greater than any possible int value.

I liked overrloading comparison operator method from this answer, but how do you initialize the vector with infinitytype class objects if there are supposed to be an int?

Or maybe you know any better solution?

Thank you.

Upvotes: 0

Views: 1921

Answers (4)

einpoklum
einpoklum

Reputation: 132300

The solution depends on the assumptions your algorithm (or the implementation of your algorithm) has:

  • You could increase the element size beyond int (e.g. if your sizeof(int) is 4, use int64_t), and initialize to (int64_t) 1 + std::numeric_limits<int>:max() (and similarly for the negative values). But perhaps your algorithm assumes that you can't "exceed infinity" by adding on multiplying by positive numbers?
  • You could use an std::variant like other answers suggest, selecting between an int and infinity; but perhaps your algorithm assumes your elements behave like numbers?
  • You could use a ratio-based "number" class, ensuring it will not get non-integral values except infinity.
  • You could have your algorithm special-case the maximum and minimum integers
  • You could use floats or doubles which support -/+ infinity, and restrict them to integrality.
  • etc.

So, again, it really just depends and there's no one-size-fits-all solution.

Upvotes: 2

MSalters
MSalters

Reputation: 180295

You are already aware of the idea of an "infinite" type, but that implementation could only contain infinite values. There's another related idea:

struct extended_int {
  enum {NEGINF, FINITE, POSINF} type;
  int finiteValue; // Only meaningful when type==FINITE

  bool operator<(extended_int rhs) {
    if (this->type==POSINF) return false;
    if (rhs.type==NEGINF) return false;
    if (this->type==FINITE && rhs.type==POSINF) return false;
    if (this->type==NEGINF && rhs.type==FINITE) return false;
    assert(this->type==FINITE && rhs.type==FINITE);
    return this->finiteValue < rhs.finiteValue)
  }

  // Implicitly converting ctor
  constexpr extended_int(int value) : type(FINITE), finiteValue(value) { }
  // And the two infinities
  static constexpr extended_int posinf;
  static constexpr extended_int neginf;
}

You now have extended_int(5) < extended_int(6) but also extended_int(5) < extended_int::posinf

Upvotes: 0

petersohn
petersohn

Reputation: 11730

You can use a variant (for example, boost::variant) which supports double dispatching, which stores either an int or an infinitytype (which should store the sign of the infinity, for example in a bool), then implement the comparison operators through a visitor.

But I think it would be simpler if you simply used a double instead of int, and whenever you take out a value that is not infinity, convert it to int. If performance is not that great of an issue, then it will work fine (probably still faster than a variant). If you need great performance, then just use MAX_INT and be done with it.

Upvotes: 0

lisyarus
lisyarus

Reputation: 15586

AS already said in the comments, you can't have an infinity value stored in int: all values of this type are well-defined and finite.

If you are ok with a vector of something working as an infinite for ints, then consider using a type like this:

struct infinite
{ };

bool operator < (int, infinite)
{
    return true;
}

Upvotes: 1

Related Questions