调用此模板时如何避免必须使用 decltype?

How can I avoid having to use decltype when calling this template?

我有以下代码,我用它来自动捕获 bad_variant_access 错误。我知道我可以使用 get_if 来简化错误处理,但在这种特殊情况下,我不需要指针。这段代码似乎有效,但却是多余的。如您所见,我总是必须做 assert_no_bad_variant_access<decltype(v), int>(v, "msg");。我可以以某种方式简化它以避免必须通过 decltype(v) 吗?我觉得罗嗦。

理想情况下,我想要一个模板,我只需要将其传递给 get_Tvariant_T 应该以某种方式自动确定。

Play with the code.

template <typename variant_T, typename get_T>
get_T assert_no_bad_variant_access(variant_T& v, std::string_view msg) {
  try {
    return std::get<get_T>(v);
  } catch (const std::bad_variant_access& bva) {
    std::cout << msg << '\n';
    get_T t;
    return t;
  }
}

int main() 
{

    std::variant<int, double, std::string> v = "hi there!";
    auto result1 = assert_no_bad_variant_access<decltype(v), std::string>(v, "std::string failed");
    auto result2 = assert_no_bad_variant_access<decltype(v), int>(v, "int failed");
    return 0;   
}

重新排序模板参数。让variant_T排在第二位,这样就可以推导出

template <typename get_T, typename variant_T>
get_T assert_no_bad_variant_access(variant_T& v, std::string_view msg) {
  try {
    return std::get<get_T>(v);
  } catch (const std::bad_variant_access& bva) {
    std::cout << msg << '\n';
    get_T t;
    return t;
  }
}

int main() 
{

    std::variant<int, double, std::string> v = "hi there!";
    auto result1 = assert_no_bad_variant_access<std::string>(v, "std::string failed");
    auto result2 = assert_no_bad_variant_access<int>(v, "int failed");
    return 0;   
}

记住,只有在可以推导出 尾部 参数的情况下,我们才能指定部分模板参数。

顺便说一句,您不需要使用异常来检测这种情况。 std::variant API 包括 std::holds_alternative。你可以直接查看。这将避免对常规控制流使用异常。