在 std::visit 中跳过变体类型的一些重载组合的方法是什么?



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...>;

最新更新