Because Foo has no default constructor, you cannot initialize a Foo array without C++11's list-initialization.
Your first option is to use a version of C++ that isn't two decades old, but I suppose that's not an option for you, otherwise you would not be asking this.
There are a few other options, but none of them (as far as I know) allow you to keep the array intact.
Use dynamic allocation
struct BarNew {
    Foo* foos;
    BarNew(int i) : foos(static_cast<Foo*>(::operator new(sizeof(Foo) * 2)))
    {
        new (foos + 0) Foo(i+1, i+2);
        new (foos + 1) Foo(i+2, i+3);
    }
};
This can look complicated because you cannot use new directly without calling the constructor, and that's not possible for an array (again, only prior to C++11). Calling ::operator new allocates without initializing, just like malloc does in C. You then need to use placement-new to actually construct each object.
Use std::vector
struct BarVector {
    std::vector<Foo> foos;
    BarVector(int i)
    {
        foos.reserve(2);
        foos.push_back(Foo(i+1, i+2));
        foos.push_back(Foo(i+2, i+3));
    }
};
This is the simplest option, with the main drawback being that is also uses dynamic allocation, unlike an array. The call to reserve is of course optional.
Use an array wrapper
template<class T, std::size_t N>
struct ArrayWrapper {
    union {
        char buffer[sizeof(T)];
        unsigned long long dummy;
    } storage[N];
    T& operator[](std::size_t i) {
        return reinterpret_cast<T&>(storage[i]);
    }
};
struct BarStruct {
private:
    static ArrayWrapper<Foo, 2> foos_init(int i) {
        ArrayWrapper<Foo, 2> foos;
        foos[0] = Foo(i+1, i+2);
        foos[1] = Foo(i+2, i+3);
        return foos;
    }
public:
    ArrayWrapper<Foo, 2> foos;
    BarStruct(int i) : foos(foos_init(i))
    {
    }
};
This is the most complicated of these three options, but it has the advantage of not using dynamic allocation. It can be made to behave much like a simple array.
The ArrayWrapper struct here is generic, so you can use it for types other than Foo. It contains a buffer (array of char) to contain each Foo object, and uses a union for alignment purposes, because alignas is, again, a C++11 addition. I'm not 100% confident it works in every case; I think you have to pray that unsigned long long has a good enough alignment. If sizeof(T) < sizeof(unsigned long long), you will be wasting some space, but you could write a template specialization if that worries you.
foos_init exists only to provide the initialization values. After the constructor, you can use foos like an array.
See that all three options compile in C++03.
There is yet another option I can think of, but I'm not confident enough that it would work or in my abilities to write it, so I'm leaving it as an idea. It's a combination of options 2 and 3, where you would provide a storage on the stack just like ArrayWrapper::storage, but then use it for a std::vector thanks to the "allocator" feature (the second template argument of std::vector). That way, you get all the fancy methods of a std::vector without allocating anything on the heap.