using declaration in variadic template

狂风中的少年 提交于 2019-11-27 06:41:22

Ok i found out a pretty decent solution:

basically i need to unpack one extra lambda case and apply the using clause to the unpacked lambda and the rest, but in this case, since i apparently i cannot make a variadic list of using declarations (at least i don't know the syntax, if its possible), the rest is wrapped by inheriting from the 'rest' case, like this:

template <typename ReturnType, typename... Lambdas>
struct lambda_visitor;

template <typename ReturnType, typename Lambda1, typename... Lambdas>
struct lambda_visitor< ReturnType, Lambda1 , Lambdas...> 
  : public lambda_visitor<ReturnType, Lambdas...>, public Lambda1 {

    using Lambda1::operator();
    using lambda_visitor< ReturnType , Lambdas...>::operator();
    lambda_visitor(Lambda1 l1, Lambdas... lambdas) 
      : Lambda1(l1), lambda_visitor< ReturnType , Lambdas...> (lambdas...)
    {}
};


template <typename ReturnType, typename Lambda1>
struct lambda_visitor<ReturnType, Lambda1> 
  : public boost::static_visitor<ReturnType>, public Lambda1 {

    using Lambda1::operator();
    lambda_visitor(Lambda1 l1) 
      : boost::static_visitor<ReturnType>(), Lambda1(l1)
    {}
};


template <typename ReturnType>
struct lambda_visitor<ReturnType> 
  : public boost::static_visitor<ReturnType> {

    lambda_visitor() : boost::static_visitor<ReturnType>() {}
};

So i can do this inductively by placing two using declarations, one from the unpacked lambda type and another from the parent class, which is actually the same class with one less lambda.

This is an old question and a great answer. There's one more thing we can do to improve it IMHO.

In c++14 and better we don't need to specify the return type - it can be deduced.

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

namespace detail {

    template<typename... Lambdas>
    struct lambda_visitor;

    template<typename Lambda1, typename... Lambdas>
    struct lambda_visitor<Lambda1, Lambdas...>
        : public lambda_visitor<Lambdas...>,
          public Lambda1
    {

        using Lambda1::operator ();
        using lambda_visitor<Lambdas...>::operator ();

        lambda_visitor(Lambda1 l1, Lambdas... lambdas)
            : Lambda1(l1)
            , lambda_visitor<Lambdas...>(lambdas...) {}
    };

    template<typename Lambda1>
    struct lambda_visitor<Lambda1>
        :
            public Lambda1
    {

        using Lambda1::operator ();

        lambda_visitor(Lambda1 l1)
            : Lambda1(l1) {}
    };
}

template<class...Fs>
auto compose(Fs&& ...fs)
{
    using visitor_type = detail::lambda_visitor<std::decay_t<Fs>...>;
    return visitor_type(std::forward<Fs>(fs)...);
};

use case:

boost::variant<int, std::string> x = "foo", y = 4;

auto visitor = compose([](const int& i)
                       {
                           std::cout << i << std::endl;
                       },
                       [](const std::string& s)
                       {
                           std::cout << s << std::endl;
                       });

boost::apply_visitor(visitor, x);
boost::apply_visitor(visitor, y);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!