std::visit
支持多种输入变体。但是,代码应处理这些变体中类型的所有组合。
有没有办法跳过不"有意义"的组合?
例如:
template<class... Ts>
struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
int main() {
std::variant<int, float, char> v1 { 's' };
std::variant<int, float, char> v2 { 10 };
std::visit(overloaded{
[](int a, int b) { },
[](int a, float b) { },
[](int a, char b) { },
[](float a, int b) { },
[](float a, float b) { },
[](float a, char b) { },
[](char a, int b) { },
[](char a, float b) { },
[](char a, char b) { }
}, v1, v2);
return 0;
}
是否有机会只实施几个重要的组合,而"留下"其余的? (当然,现在编译器会报告令人讨厌的错误,如果你忘记实现一个组合......
也许是通用的 lambda?
std::visit(overloaded{
[](int a, int b) { },
[](int a, float b) { },
[](int a, char b) { },
[](float a, int b) { },
[](auto a, auto b) { }, // <<
}, v1, v2);
这有效,但我想知道是否有更好的解决方案?
更新: 这是答案中提到的解决方案的游乐场: http://coliru.stacked-crooked.com/a/78d9f2f25789bad2
是的,通用 lambda 是一个很好的解决方案。您提出的解决方案确实适用于垃圾。
通常的重载规则适用。
[](auto a, auto b)
在这个意义上等同于
template <class T1, class T2> auto foo(T1 a, T2 b) const;
任何与非模板化重载之一不完全匹配的内容都将调用通用 lambda。
您可以通过提供类似的东西来混合一些东西[] (int a, auto b)
和[] (auto a, auto b)
.通常的重载规则仍然适用。
或者用[]<class T>(T a, T b)
把事情混合得更多(自 C++20 起(
另一种选择是将overloaded
更改为如下所示的内容:
template<class... Ts>
struct overloaded_or_no_op : Ts...
{
using Ts::operator()...;
template<class... Us>
void operator()(const Us&...) const { }
};
template<class... Ts> overloaded_or_no_op(Ts...) -> overloaded_or_no_op<Ts...>;