gpt4 book ai didi

c++ - 如何定义采用可变类模板的函数?

转载 作者:行者123 更新时间:2023-12-05 03:18:21 27 4
gpt4 key购买 nike

我正在尝试定义一个简单的基于变体的结果类型别名,有点像穷人生锈的结果类型:

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;

即一个Result_t只是一个 std::variant 0在哪里第一个索引是成功的结果,其余是错误结构。

我定义了这个辅助方法来检查结果是否良好:

template <typename SuccessType, typename... ErrorTypes>
inline bool Ok(const Result_t<SuccessType, ErrorTypes...>& r) {
return r.index() == 0;
}

但是当我尝试实例化它时,出现“找不到匹配的重载函数”:

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);
}

我做错了什么?如果我只有 Oktemplate <typename T> Ok(const T& r)一样被模板化它有效,但使功能过于笼统。

最佳答案

展开Result_t之后函数参数中的别名,看起来像这样:

template <typename SuccessType, typename... ErrorTypes>
bool Ok(const detail::Result<SuccessType, ErrorTypes...>::type& r) {
return r.index() == 0;
}

这里有问题的部分是模板参数留在名称解析运算符 :: 的左侧. :: 剩下的一切是一个非推导上下文,这意味着它不用于推导模板参数。所以自 SuccessTypeErrorTypes...仅出现在非推导上下文中,无法推导它们,并且未明确指定它们的调用将失败。

你可以看到这条规则是必要的,因为理论上 detail::Result<SuccessType, ErrorTypes...> 的任何特化可以有一个 ::type匹配参数类型。编译器无法针对每种可能的类型组合进行检查。

与其尝试为类型别名,不如制作 Result一个实际的新类型:

template <typename SuccessType, typename... ErrorTypes>
struct Result {
using variant_type = std::variant<SuccessType, ErrorTypes...>;
variant_type variant;
};

template <typename... ErrorTypes>
struct Result<void, ErrorTypes...> {
using variant_type = std::variant<std::monostate, ErrorTypes...>;
variant_type variant;
};

template <typename SuccessType, typename... ErrorTypes>
bool Ok(const Result<SuccessType, ErrorTypes...>& r) {
return r.variant.index() == 0;
}

或类似的东西。如果您真的想使用仅使用别名的旧设计,那么该函数不应将嵌套别名作为参数,而应将实际类型作为参数(这可能与设计意图不符):

template <typename T, typename... ErrorTypes>
bool Ok(const std::variant<T, ErrorTypes...>& r) {
return r.index() == 0;
}

(我删除了模板上的 inline。函数模板上的 inline 没有多大意义。)

关于c++ - 如何定义采用可变类模板的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73750633/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com