I have following piece of code:
#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;
}
stdout :
string
dict
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: wrong type
I have element_type
containing several types. Basically I consider it to contain string
and element_dict
. Here I have situation when somebody added int
type to element_type
, but forgot to provide required fixes to foo
function. Now I detect this situation in run-time throwing exception. Is there any way to detect it in compile-time?
The easiest way to get that situation to fail at compile-time is to simply not include the overload lambda that catches non-string
and non-element_dict
typed items; that is, remove
[](auto /*elements*/) { throw std::runtime_error("wrong type"); }
Then it will fail at compile-time. Basically, by including that case, you are specifically telling the compiler that you want it to succeed at compiling such cases; you are opting-in to behavior you don't want.