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
答案 0 :(得分:7)
是的,通用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起)混合使用
答案 1 :(得分:3)
另一种选择是将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...>;