idmap2: replace std::pair<bool, T> with Result<T>

Introduce a new type Result<T> to indicate if an operation succeeded or
not, and if it did, to hold the return value of the operation. This is
the same as how std::pair<bool, T> is already used in the codebase, so
replace all instances with Result<T> to improve clarity.

Result<T> is simply an alias for std::optional<T>. The difference is
semantic: use Result<T> as the return value for functions that can fail,
use std::optional<T> when values are truly optional. This is modelled
after Rust's std::result and std::option.

A future change may graduate Result<T> to a proper class which can hold
additional details on why an operation failed, such as a string or an
error code. As a special case, continue to use std::unique_ptr<T>
instead of Result<std::unique_ptr<T>> for now: the latter would increase
code complexity without added benefit.

Test: make idmap2_tests
Change-Id: I2a8355107ed2b6485409e5e655a84cf1e20b9911
diff --git a/cmds/idmap2/tests/ZipFileTests.cpp b/cmds/idmap2/tests/ZipFileTests.cpp
index a504d31..6e4a501 100644
--- a/cmds/idmap2/tests/ZipFileTests.cpp
+++ b/cmds/idmap2/tests/ZipFileTests.cpp
@@ -16,8 +16,8 @@
 
 #include <cstdio>  // fclose
 #include <string>
-#include <utility>
 
+#include "idmap2/Result.h"
 #include "idmap2/ZipFile.h"
 
 #include "gmock/gmock.h"
@@ -44,14 +44,12 @@
   auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
   ASSERT_THAT(zip, NotNull());
 
-  bool status;
-  uint32_t crc;
-  std::tie(status, crc) = zip->Crc("AndroidManifest.xml");
-  ASSERT_TRUE(status);
-  ASSERT_EQ(crc, 0x762f3d24);
+  Result<uint32_t> crc = zip->Crc("AndroidManifest.xml");
+  ASSERT_TRUE(crc);
+  ASSERT_EQ(*crc, 0x762f3d24);
 
-  std::tie(status, std::ignore) = zip->Crc("does-not-exist");
-  ASSERT_FALSE(status);
+  Result<uint32_t> crc2 = zip->Crc("does-not-exist");
+  ASSERT_FALSE(crc2);
 }
 
 TEST(ZipFileTests, Uncompress) {