c++ - 具有不同返回类型的变体访问者

标签 c++ variant boost-variant

考虑以下使用 boost::variant 的代码片段(但也应该非常适用于 std::variant)。

#include <vector>
#include <boost/variant.hpp>

int main()
{
    boost::variant<std::vector<int>, std::vector<double> > vr 
        = std::vector<int>(5, 5);;

    // OK, no problem.
    boost::apply_visitor([](auto a) { std::cout << a[0] << "\n"; }, vr);

    // ERROR: return types must not differ.
    //boost::apply_visitor([](auto a) { return a.begin(); }, vr);
}

在这里,我们有一个变体会吞噬不同类型的标准 vector (例如,本例中的 intdouble),我们希望有一个返回不同类型对象的访问者(在本例中,指向底层容器开头的迭代器)。但是,这显然不会编译 std::vector<int>::iteratorstd::vector<double>::iterator 不同.是否有一种巧妙的方法可以从根本上实现这一目标,可能是通过一个额外的间接层?

最佳答案

您可以返回不同的变体

#include <iostream>
#include <vector>
#include <boost/variant.hpp>

int main()
{
    boost::variant<std::vector<int>, std::vector<double> > vr 
        = std::vector<int>(5, 5);
    using iter_variant = boost::variant<std::vector<int>::iterator, std::vector<double>::iterator >;

    using value_variant = boost::variant<int, double>;

    // OK, no problem.
    boost::apply_visitor([](auto a) { std::cout << a[0] << "\n"; }, vr);

    // Also OK
    boost::apply_visitor([](auto a) -> iter_variant { return a.begin(); }, vr);

    // Also OK
    boost::apply_visitor([](auto a) -> value_variant { return a[0]; }, vr);
}

See it live

给定一个通用的 lambda 和一个变体,您可以获得合适的返回类型。

template<typename Func, typename Variant>
struct visitor_result;

template<typename Func, typename ... Ts>
struct visitor_result<Func, boost::variant<Ts...>>
{
    using type = boost::variant<decltype(std::declval<Func>()(std::declval<Ts>()))...>;
};

template<typename Func, typename Variant>
using visitor_result_t = typename visitor_result<Func, Variant>::type;

template<typename Func, typename Variant>
visitor_result_t<Func, Variant> generic_visit(Func func, Variant variant)
{
    return boost::apply_visitor([&](auto a) -> visitor_result_t<Func, Variant> { return func(a); }, variant);
}

See it live

关于c++ - 具有不同返回类型的变体访问者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56598420/

相关文章:

c++ - Xcode 6 : Create pure C++ OpenGL application bundle (. 应用程序)不使用 "Cocoa Application"模板

casting - 转换相同底层类型的枚举变体

c# - 类型推断变量

c++ - 您将如何使用 C++/Qt5 构建无窗口应用程序?

c++ - C++ 类中的错误 C2280 互斥体

c++ - 它是 opencv RotatedRect 的错误吗?

mysql - 如何从 MySQL ROW 类型创建数组?

c++ - 如何返回可变数量的各种类型的容器?

C++ - 如何键入别名、typedef 或包装 boost::variant?

c++ - 是否需要 boost::variant 访问者类?