Why does reading a record struct fields from std::istream fail, and how can I fix it?

One viable solution is to reorder input fields (if this is possible)

ID      Age Forename Lastname
1267867 32  John     Smith    
67545   36  Jane     Doe      
8677453 56  Gwyneth  Miller   
75543   23  J. Ross  Unusual  
...

and read in the records as follows

#include <iostream>
#include <vector>

struct Person {
    unsigned int id;
    std::string name;
    uint8_t age;
    // ...
};

int main() {
    std::istream& ifs = std::cin; // Open file alternatively
    std::vector<Person> persons;

    Person actRecord;
    unsigned int age;
    while(ifs >> actRecord.id >> age && 
          std::getline(ifs, actRecord.name)) {
        actRecord.age = uint8_t(age);
        persons.push_back(actRecord);
    }

    return 0;
}

You have whitespace between firstname and lastname. Change your class to have firstname and lastname as separate strings and it should work. The other thing you can do is to read in two separate variables such as name1 and name2 and assign it as

actRecord.name = name1 + " " + name2;

Here's an implementation of a manipulator I came up with that counts the delimiter through each extracted character. Using the number of delimiters you specify, it will extract words from the input stream. Here's a working demo.

template<class charT>
struct word_inserter_impl {
    word_inserter_impl(std::size_t words, std::basic_string<charT>& str, charT delim)
        : str_(str)
        , delim_(delim)
        , words_(words)
    { }

    friend std::basic_istream<charT>&
    operator>>(std::basic_istream<charT>& is, const word_inserter_impl<charT>& wi) {
        typename std::basic_istream<charT>::sentry ok(is);

        if (ok) {
            std::istreambuf_iterator<charT> it(is), end;
            std::back_insert_iterator<std::string> dest(wi.str_);

            while (it != end && wi.words_) {
                if (*it == wi.delim_ && --wi.words_ == 0) {
                    break;
                }
                dest++ = *it++;
            }
        }
        return is;
    }
private:
    std::basic_string<charT>& str_;
    charT delim_;
    mutable std::size_t words_;
};

template<class charT=char>
word_inserter_impl<charT> word_inserter(std::size_t words, std::basic_string<charT>& str, charT delim = charT(' ')) {
    return word_inserter_impl<charT>(words, str, delim);
}

Now you can just do:

while (ifs >> actRecord.id >> word_inserter(2, actRecord.name) >> actRecord.age) {
    std::cout << actRecord.id << " " << actRecord.name << " " << actRecord.age << '\n';
}

Live Demo