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



我有以下一段代码:

#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 << "stringn"; },
[](element_dict element) { cout << "dictn";},
[](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;
}

stdout:

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

我有包含几种类型的element_type。基本上我认为它包含stringelement_dict。在这里,我有这样的情况:有人将int类型添加到element_type,但忘记为foo功能提供所需的修复。现在我在运行时抛出异常中检测到这种情况。有什么方法可以在编译时检测它吗?

使这种情况在编译时失败的最简单方法是简单地不包含捕获非string和非element_dict类型项的重载lambda;也就是说,删除

[](auto /*elements*/) { throw std::runtime_error("wrong type"); }

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