如何在编译时捕获持有错误类型的 std::variant?

3

我有以下的代码:

#include <iostream>
#include <string>
#include <map>
#include <variant>

using namespace std;

template <class... Ts>
struct overloaded : Ts...
{
    using Ts::operator()...;
};
template <class... Ts>
overloaded(Ts...)->overloaded<Ts...>;

using element_dict = std::map<string, string>;
using element_type = std::variant<string, element_dict, int>;

void foo(element_type elements)
{
    std::visit(overloaded{
            [](string element) { cout << "string\n"; },
            [](element_dict element) { cout << "dict\n";},
            [](auto /*elements*/) { throw std::runtime_error("wrong type"); }
        }, elements);
}

int main()
{
    element_type str_elems = "string_elem";
    foo(str_elems);
    element_type dict_elems = element_dict{ {"string", "string"} };
    foo(dict_elems);
    element_type wrong_type_elems = 5;
    foo(wrong_type_elems); // throws error

    return 0;
}

标准输出:

string
dict
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: wrong type

我有一个包含多种类型的element_type。基本上,我认为它包含stringelement_dict。在这里,当有人将int类型添加到element_type中,但忘记为foo函数提供所需的修复时,我就会检测到运行时异常。有没有办法在编译时检测到这种情况?


1
是的。删除[](auto /*elements*/)重载。该重载将编译时错误“转换”为运行时异常。 - Drew Dormann
你认为为什么需要第三个重载呢? - Ayxan Haqverdili
1个回答

2
将非 string 和非 element_dict 类型的项捕获的重载 lambda 函数不包含在内是让编译时出现错误的最简单方法;也就是说,删除它即可。
[](auto /*elements*/) { throw std::runtime_error("wrong type"); }

那么它将在编译时失败。基本上,通过包含这种情况,您明确告诉编译器您希望它成功编译这些情况; 您正在选择不想要的行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接