Find untagged template options/parameters/args by position

孤街浪徒 提交于 2019-12-02 06:41:59

I have managed to get it working

(specialization of already presented option pack helper, merge with original code)

template<class... Tags> struct tags {
    template<class Option> static constexpr bool match() {
        return false; }};
template<class First, class... More> struct tags<First, More...> {
    template<class Option> static constexpr bool match() {
        return std::is_same<First, Option>::value
          || std::is_base_of<First, Option>::value
          || tags<More...>::template match<Option>(); }};
//-----------------------------------------------------------------------
template<class... Tags, class... Opts>
  struct bind<tags<Tags...>, Opts...> {
    static constexpr size_t size = sizeof...(Opts);
    typedef opt::tags<Tags...> tags;
    template<class Tag> static constexpr bool has() {
        return false; }
    template<class Tag, class Default = void>
      using get = Default;
    template<size_t idx, class Default = void>
      using at = Default;
    static constexpr size_t count = 0; };
template<class... Tags, class First, class... More>
  struct bind<tags<Tags...>, First, More...> {
public:
    typedef opt::tags<Tags...> tags;
    static constexpr size_t size = 1 + sizeof...(More);
private:
    template<size_t idx, class Default, bool> struct at_ {
        typedef typename bind<tags, More...>::template at<idx,Default> type; };
    template<size_t idx, class Default> struct at_<idx, Default, false> {
        typedef typename bind<tags, More...>::template at<idx-1,Default> type; };
    template<class Default> struct at_<0, Default, false> {
        typedef First type; };
public:
    template<class Tag> static constexpr bool has() {
        return bind<First, More...>::template has<Tag>(); }
    template<class Tag, class Default = void>
      using get = typename bind<First, More...>::template get<Tag,Default>;
    template<size_t idx, class Default = void>
      using at = typename at_<idx, Default, tags::template match<First>()>::type;
    static constexpr size_t count = bind<tags, More...>::count
      + (tags::template match<First>() ? 0 : 1); };

Usage

template <class... Opts> class rqueue {
//  bind tags and options
    typedef opt::bind<opt::tags<tag::allocator,
      tag::virtual_offset, tag::fill_empty,
      tag::reconstructible, tag::fixed_size>,
      Opts...> opts;
public:
//  get first untagged option or byte if none
    typedef typename opts::template at<0,byte>
      value_type, record_type, *pointer, &reference;
//  get second untagged option, or allocator option or std::allocator<byte>
    typedef typename std::conditional<
      (opts::count > 1),
      typename opts::template at<1>,
      typename opts::template get<tag::allocator,
      std::allocator<byte>>>::type allocator_type;
//...shorter version of the above
    typedef typename opts::template at<1,
      typename opts::template get<tag::allocator,
      std::allocator<byte>>> allocator_type_v2;
//  get type specified as virtual_offset or void
    typedef typename opts::template get<tag::virtual_offset,
      std::enable_if<true>>::type offset_type;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!