I am trying to define a simple variant-based Result type alias, sort of like a poor man's rust-like Result type :
namespace detail {
template <typename SuccessType, typename... ErrorTypes>
struct Result {
using type = std::variant<SuccessType, ErrorTypes...>;
};
template <typename... ErrorTypes>
struct Result<void, ErrorTypes...> {
using type = std::variant<std::monostate, ErrorTypes...>;
};
} // namespace detail
template <typename SuccessType, typename... ErrorTypes>
using Result_t = detail::Result<SuccessType, ErrorTypes...>::type;
i.e. a Result_t is just an std::variant where the 0th index is the successful result and the rest are error structs.
I defined this helper method to check if the result is good:
template <typename SuccessType, typename... ErrorTypes>
inline bool Ok(const Result_t<SuccessType, ErrorTypes...>& r) {
return r.index() == 0;
}
But I get a "no matching overloaded function found" when I try to instantiate it:
error C2672: 'Ok': no matching overloaded function found
error C2783: 'bool Ok(const detail::Result<SuccessType,ErrorTypes...>::type &)': could not deduce template argument for 'SuccessType'
struct FileError {};
struct BadJson {};
template <typename T>
using Result = Result_t<T, FileError, BadJson>;
Result<void> GetVoid() { return {}; }
TEST(ConfigFileTest, Result) {
auto res = GetVoid();
EXPECT_EQ(res.index(), 0);
bool ok = Ok(res);
EXPECT_TRUE(ok);
}
What am I doing wrong? If I just have Ok be templated like template <typename T> Ok(const T& r) it works, but makes the function too general.