If you feel a need to write it yourself instead of using a ready library, you could use a std::unordered_map<> and add some streaming and extraction support around it. Here's an example with comments in the code:
#include <string>
#include <unordered_map>
class KeyValue { //        Key          Value    
    std::unordered_map<std::string, std::string> m_kv{};
public:
    // at() is used to get a reference to a Value given the supplied Key. It uses
    // the function with the same name in the unordered_map.
    inline std::string& at(const std::string& Key) { return m_kv.at(Key); }
    inline const std::string& at(const std::string& Key) const { return m_kv.at(Key); }
    // The "as<T>" function below is used to extract values from the map.
    // The exact version of the function that will be used depends on the type
    // you want to extract from the string. Explicit specializations of the function
    // are declared outside the class.
    // A generic conversion function to anything that can be constructed from a std::string
    template<typename T>
    T as(const std::string& Key) const {
        return at(Key);
    }
    // A function to extract directly into a variable using the proper as<T>
    template<typename T>
    void extract_to(T& var, const std::string& Key) const {
        var = as<T>(Key);
    }
    // A friend function to read from an input stream (like an open file) and
    // populate the unordered_map.
    friend std::istream& operator>>(std::istream&, KeyValue&);
};
// Explicit specializations of KeyValue::as<T>()
// floats
template<>
float KeyValue::as(const std::string& Key) const {
    return std::stof(at(Key));
}
template<>
double KeyValue::as(const std::string& Key) const {
    return std::stod(at(Key));
}
template<>
long double KeyValue::as(const std::string& Key) const {
    return std::stold(at(Key));
}
// signed integers
template<>
int KeyValue::as(const std::string& Key) const {
    return std::stoi(at(Key));
}
template<>
long KeyValue::as(const std::string& Key) const {
    return std::stol(at(Key));
}
template<>
long long KeyValue::as(const std::string& Key) const {
    return std::stoll(at(Key));
}
// unsigned integers
template<>
unsigned KeyValue::as(const std::string& Key) const {
    return std::stoul(at(Key));
}
template<>
unsigned long KeyValue::as(const std::string& Key) const {
    return std::stoul(at(Key));
}
template<>
unsigned long long KeyValue::as(const std::string& Key) const {
    return std::stoull(at(Key));
}
// bool
template<>
bool KeyValue::as(const std::string& Key) const {
    const std::string& val = at(Key);
    if(val=="true" || val=="1") return true;
    else if(val=="false" || val=="0") return false;
    throw std::range_error("\"" + Key + "\" is neither true nor false");
}   
// the friend function that extracts key value strings from a stream
std::istream& operator>>(std::istream& is, KeyValue& kv) {
    std::string line;
    // read one line at a time
    while(std::getline(is, line)) {
        auto pos = line.find('=');
        if(pos == std::string::npos || pos == 0) {
            // if '=' was not found (or found at pos 0), set the failbit on the stream
            is.setstate(std::ios::failbit);
        } else {
            // if '=' was found, put the Key and Value in the map by
            // using substr() to split the line where the '=' was found
            kv.m_kv.emplace(line.substr(0, pos), line.substr(pos + 1));
        }
    }
    return is;
}
With that in place, you can read a file and populate the variables that you've preferably put in a class / struct. Example:
#include <fstream>
struct Variables {
    std::string Name{};
    unsigned int Age{};
    std::string Gender{};
    double PI{};
    bool Hungry{};
    bool Sad{};
    Variables(const std::string& filename) {
        std::ifstream is(filename);
        if(is) {
            KeyValue tmp;
            is >> tmp; // stream the whole file into tmp
            // extract values
            tmp.extract_to(Name, "Name");
            tmp.extract_to(Age, "Age");
            tmp.extract_to(Gender, "Gender");
            tmp.extract_to(PI, "PI");
            tmp.extract_to(Hungry, "Hungry");
            tmp.extract_to(Sad, "Sad");
        } else throw std::runtime_error("Could not read \""+filename+"\".");
    }
};
Example data file (vars.dat):
Name=No name
Age=8
Gender=male
PI=3.14159
Hungry=true
Sad=false
...and a main example::
#include <iostream>
int main() {
    try {
        Variables var("vars.dat"); // open file and populate variables
        std::cout << std::boolalpha
            << "Name:   " << var.Name << "\n"
            << "Age:    " << var.Age << "\n"
            << "Gender: " << var.Gender << "\n"
            << "PI:     " << var.PI << "\n"
            << "Hungry: " << var.Hungry << "\n"
            << "Sad:    " << var.Sad << "\n";
    } catch(const std::exception& ex) {
        std::cerr << ex.what() << "\n";
    }
}