繁体   English   中英

如何根据 function 特征将 std::index_sequence 参数传递给嵌套模板结构

[英]How to pass std::index_sequence param to an nested-template struct according to function traits

这是我的简单代码,它确实有效(我将单个 integer 传递给argument ):

#include <iostream>
#include <tuple>
#include <string>
#include "boost/variant.hpp"

using TObjList = std::vector<boost::variant<std::string, int>>;

template<typename> struct FTrait;
template<typename R, typename... A> struct FTrait<R(A...)> {
    using RetType = R;
    using ArgsTuple = std::tuple<A...>;
    static constexpr std::size_t arity = sizeof...(A);

    template<size_t N> struct argument {
        static_assert( N < arity , "error: invalid argument index");
        typedef typename std::tuple_element_t<N, std::tuple<A...>> type;
    };
};
void Show(const std::string& s, int a) {
    std::cout << s << "\n" << a << "\n";
}

int main() {
    TObjList list;
    list.emplace_back("hello");
    list.emplace_back(567);
    Show(boost::get<FTrait<decltype(Show)>::argument<0>::type>(list[0]),
         boost::get<FTrait<decltype(Show)>::argument<1>::type>(list[1]));
}

但是下面的代码不起作用(也许我将一个序列传递给了argument ):

#include <iostream>
#include <tuple>
#include <string>
#include "boost/variant.hpp"

using TObjList = std::vector<boost::variant<std::string, int>>;

template<typename> struct FTrait;
template<typename R, typename... A> struct FTrait<R(A...)> {
    using RetType = R;
    using ArgsTuple = std::tuple<A...>;
    static constexpr std::size_t arity = sizeof...(A);

    template<size_t N> struct argument {
        static_assert( N < arity , "error: invalid argument index");
        typedef typename std::tuple_element_t<N, std::tuple<A...>> type;
    };
};

// here is new code
template<typename T> struct ConvertOne {
    T operator () (const TObjList& List, size_t Index) {
        if ( Index < List.size() ) {
            return boost::get<T>(List[Index]);
        }
    }
};

template<typename F, size_t... Index>
void MyCall(const F& Func, const TObjList& List, const std::index_sequence<Index...>&) {
    // This code not work:
    Func(ConvertOne<typename FTrait<F>::argument<Index>::type>{}(List, Index)...);

    // These code would work:
    // using ArgsTuple = typename FTrait<F>::ArgsTuple;
    // Func(ConvertOne<std::decay_t<typename std::tuple_element_t<Index, ArgsTuple>>>{}(List, Index)...);
}
// new code done

void Show(const std::string& s, int a) {
    std::cout << s << "\n" << a << "\n";
}

int main() {
    TObjList list;
    list.emplace_back("hello");
    list.emplace_back(567);
    // new invoke
    MyCall(Show, list, std::make_index_sequence<FTrait<decltype(Show)>::arity>{});
}

此代码会引发编译错误:

ftrait.cpp: In function ‘void MyCall(const F&, const TObjList&, std::index_sequence<Index ...>&)’:
ftrait.cpp:34:62: error: template argument 1 is invalid
     Func(ConvertOne<typename FTrait<F>::argument<Index>::type>{}(List, Index)...);

我希望使用std::index_sequencefunction_traits让程序自动识别一个 function 的参数类型和数量,比如std::tuple_element<Index, ArgsTuple>::type boost::function_traits不能满足我,所以我尝试自己实现。 我应该怎么办? 谢谢:)

在您的情况下, typename FTrait<F>::argument<0>::typeconst std::string&

  • std::get<const std::string&>(list[0])不会编译
  • 你需要std::get<std::string>(list[0])

它可以用std::decay解决:

template<typename F, size_t... Index>
void MyCall(const F& Func, const TObjList& List, const std::index_sequence<Index...>&)
{
    Func(ConvertOne<
             typename std::decay<
                 typename FTrait<F>::template argument<Index>::type
             >::type
         >{}(List, Index)...);
}

演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM