std的优点是:访问胜过其他访问



我已经发现std::visit可以通过以下方式使用:

std::visit([](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>)
std::cout << "int with value " << arg << 'n';
else if constexpr (std::is_same_v<T, std::string>)
std::cout << "std::string with value " << std::quoted(arg) << 'n';
else 
static_assert(always_false_v<T>, "non-exhaustive visitor!");
}, v);

但相反,我想我也可以使用

if(auto x = std::get_if<int>(&v))
std::cout << " is int " << *x << std::endl;
else if(auto x = std::get_if<std::string>(&v))
std::cout << " is String " << *x << std::endl;
else
std::cout << "non-exhaustive visitor!" << std::endl;

我现在看到的唯一缺点是,当我的匹配不是详尽无遗时,我没有静态消息。使用std::visit还有其他我没有看到的优点吗?

使用std::visit还有其他我没有看到的优点吗?

是。使用std::visit,您可以使用内置的函数重载分辨率,而不是手动匹配所有类型:

template<typename... Fs> struct Overload: Fs... { using Fs::operator()...; };
template<typename... Fs> Overload(Fs...) -> Overload<Fs...>;
static_assert(visit(Overload{
[](int) { return "int"; },
[](std::string_view) { return "string_view"; },
[](auto) { return "something else"; }
}, std::variant<int, std::string_view, bool, double>{42}) == "int"sv);

此外,由于只有一个类型匹配,visit可能会编译成更快的代码,但应该检查ifs版本是否优化了其多个匹配。

更新

正如@Quentin在评论中提到的,

与手动if ladders不同,如果重载是完全匹配的,则不会选择重载,而仅当它是可调用的(如果需要,通过转换(

如果在不需要转换的地方出现过载,此技术应该会有所帮助:

[](std::same_as<int> auto) {} // C++20

template<typename T, typename U> using SameAs = std::enable_if_t<std::is_same_v<T, U>>;
[](auto t, SameAs<decltype(t), int>* = 0) {} // C++17

最新更新