Quick Start - C++ SDK
On this page
This Quick Start demonstrates how to use Realm with the Realm C++ SDK. Before you begin, ensure you have Installed the C++ SDK.
Import Realm
Make the Realm C++ SDK available in your code by including the
cpprealm/sdk.hpp
header in the translation unit where you want to use it:
Define Your Object Model
For a local-only realm you can define your object model directly in code. In this quick start, you can remove
ownerId
unless you want to add the optional Device Sync.
namespace realm { struct Todo { realm::primary_key<realm::object_id> _id{realm::object_id::generate()}; std::string name; std::string status; // The ownerId property stores the user.identifier() of a // logged-in user. Omit this property for the non-sync example. std::string ownerId; }; REALM_SCHEMA(Todo, _id, name, status, ownerId); } // namespace realm
Open a Realm
When you open a realm, you must specify a db_config. You can
optionally open a realm at a specific path, or provide a sync_config
to open a synced realm.
auto config = realm::db_config(); auto realm = realm::db(std::move(config));
For more information, see: Configure and Open a Realm.
Create, Read, Update, and Delete Objects
Once you have opened a realm, you can modify it and its objects in a write transaction block.
To instantiate a new Todo object and add it to the realm in a write block:
auto todo = realm::Todo{.name = "Create my first todo item", .status = "In Progress"}; realm.write([&] { realm.add(std::move(todo)); });
You can retrieve a live results collection of all todos in the realm:
auto todos = realm.objects<realm::Todo>();
You can also filter that collection using where:
auto todosInProgress = todos.where( [](auto const& todo) { return todo.status == "In Progress"; });
To modify a todo, update its properties in a write transaction block:
auto todoToUpdate = todosInProgress[0]; realm.write([&] { todoToUpdate.status = "Complete"; });
Finally, you can delete a todo:
realm.write([&] { realm.remove(specificTodo); });
Watch for Changes
You can watch an object for changes with the observe
method.
auto token = specificTodo.observe([&](auto&& change) { try { if (change.error) { rethrow_exception(change.error); } if (change.is_deleted) { std::cout << "The object was deleted.\n"; } else { for (auto& propertyChange : change.property_changes) { std::cout << "The object's " << propertyChange.name << " property has changed.\n"; } } } catch (std::exception const& e) { std::cerr << "Error: " << e.what() << "\n"; } });
Close a Realm
To close a realm and release all underlying resources, call db::close()
.
Closing the database invalidates any remaining objects.
realm.close();
Add Device Sync (Optional)
If you want to sync Realm data across devices, you can set up an Atlas App Services App and enable Device Sync. For more information on what you can do with App Services, see: Application Services - C++ SDK.
Prerequisites
Before you can sync Realm data, you must:
Enable Flexible Sync with Development Mode toggled to
On
. This example requires anownerId
field in your Device Sync Queryable Fields section.
Initialize the App
To use App Services features such as authentication and sync, access your App Services App using your App ID. You can find your App ID in the App Services UI.
auto appConfig = realm::App::configuration(); appConfig.app_id = APP_ID; auto app = realm::App(appConfig);
Authenticate a User
In this quick start, you use anonymous authentication to log in users without requiring them to provide any identifying information. After authenticating the user, you can open a realm for that user.
auto user = app.login(realm::App::credentials::anonymous()).get();
The Realm C++ SDK provides many additional ways to authenticate, register, and link users. For other authentication providers, see: Authenticate Users - C++ SDK
Open a Realm
Once you have enabled Device Sync and authenticated a user, you can create a sync_configuration object and open the realm. You can then add a Flexible Sync subscription that determines what data the realm can read and write.
auto syncConfig = user.flexible_sync_configuration(); auto realm = realm::db(syncConfig); // For this example, get the userId for the Flexible Sync query auto userId = user.identifier(); auto subscriptions = realm.subscriptions(); auto updateSubscriptionSuccess = subscriptions .update([&](realm::mutable_sync_subscription_set& subs) { subs.add<realm::Todo>("todos", [&userId](auto& obj) { // For this example, get only Todo items where the ownerId // property value is equal to the userId of the logged-in user. return obj.ownerId == userId; }); }) .get();
Read, Write, and React to Changes
The syntax to read, write, and watch for changes on a synced realm is identical to the syntax for non-synced realms above.
The only difference here is that this example stores the user.identifier()
of the logged-in user in the ownerId
property of the Todo
item.
This lets us query for only the user's todos in the subscription, and set
Sync permissions to Users can only read and write their own data.
For more information about Sync permissions, refer to Role-based Permissions.
auto todo = realm::Todo{.name = "Create a Sync todo item", .status = "In Progress", .ownerId = userId}; realm.write([&] { realm.add(std::move(todo)); }); auto todos = realm.objects<realm::Todo>();
While you work with local data, a background thread efficiently integrates, uploads, and downloads changesets.
Every write transaction for a subscription set has a performance cost. If you need to make multiple updates to a Realm object during a session, consider keeping edited objects in memory until all changes are complete. This improves sync performance by only writing the complete and updated object to your realm instead of every change.