Table of Contents

ABI Safety

Pimpl for compile time encapsulation

Use the Pimpl idiom judiciously to truly hide private members.

class T {
// ... all public and protected stuff goes here
private:
class impl;unique_ptr<impl> pimpl; // opaque type here
};
// End-Of-Header T.h
// T.cpp
class T::impl {
// ... all private data and functions: all for these can now change without recompiling callers
};
T:T() : pimpl(new impl) {
/* set impl values */
}
  • Avoids rebuild cascades and brittle object layouts.
  • Most appropriate for (transitively) polular types.

Use Sufficiently Portable Types and Convertions at ABI Boundaries

json-c

pkg-config --cflags --libs json-c
json_object *obj = json_tokener_parse(jsonstr);
json_object *user_id_obj;
if (json_object_object_get_ex(obj, "user_id", &user_id_obj)) {
    int user_id = json_object_get_int(user_id_obj);
}

time

std::time_t ts;
std::tm _tm;
memset(&_tm, 0, sizeof(_tm));
strptime(s.c_str(), "%Y-%m-%d %H:%M:%S", &_tm);
ts = std::mktime(&_tm);

string

template<typename OutIter>
void split(const std::string &s, char delim, OutIter it) {
    std::stringstream ss;
    ss.str(s);
    std::string item;
    while (std::getline(ss, item, delim))
        *(it++) = item;
}

std::vector<std::string> vsplit(const std::string &s, char delim) {
    std::vector<std::string> v;
    split(s, delim, std::back_inserter(v));
    return v;
}

protobuf

const ::google::protobuf::Descriptor *desc = msg->descriptor();
const ::google::protobuf::Reflection *refl = msg->GetReflection();
int nfd = desc->field_count();
for (int i = 0; i < nfd; ++i) {
    const ::google::protobuf::FieldDescriptor *fd = desc->field(i);
    const auto& it = m.find(fd->name());
    if (it == m.end()) continue;
    const std::string &v = it->second;
    switch (fd->type()) {
        case ::google::protobuf::FieldDescriptor::TYPE_DOUBLE: refl->SetDouble(msg, fd, std::stod(v)); break;
        case ::google::protobuf::FieldDescriptor::TYPE_INT32: refl->SetInt32(msg, fd, std::stoi(v)); break;
        case ::google::protobuf::FieldDescriptor::TYPE_INT64: refl->SetInt64(msg, fd, std::stol(v)); break;
        case ::google::protobuf::FieldDescriptor::TYPE_STRING: refl->SetString(msg, fd, v); break;
        default: throw std::runtime_error("unrecognized sigular field: " + fd->name());
    }
}

MySQL

#include <mysql_connection.h>
#include <mysql/mysql.h>

const std::sgtring escape_string(const std::string &s) {
    sql::mysql::MySQL_Connection *mysql_conn = dynamic_cast<sql::mysql::MySQL_Connection*>(connection);
    return mysql_conn->escapeString(s);
}

sql::Connection* connect(const std::string &host, int port, const std::string &user, const std::string &pass) {
    sql::Driver *driver = get_driver_instance();
    std::stringstream ss("tcp://");
    ss << host << ":" << port;
    return driver->connect(ss.str(), user, pass);
}

void read_kv() {
    sql::Statement *stmt = conn->createStatement();
    sql::ResultSet *res = stmt->executeQuery(sql);
    while (res->next()) m[res->getString("key")] = res->getString("name");
    delete res;
    delete stmt;
}

yaml-cpp

#include <yaml-cpp/yaml.h>

try {
    YAML::Node config = YAML::LoadFile(optarg);
    std::cout << config["database"]["host"].as<std::string>() << std::endl;
} catch (const YAML::ParserException &e) { return -1; }

OpenBLAS

facebookresearch/faiss

libsdl

OpenMPI

Microsoft/SPTAG

References