可以将模板字段参考模板参数作为第一个模板参数传递



我在 template <class Base> class foo {}中具有以下方法:

template <
    typename V,
    template <class, class> class Map,
    Map<std::string, V> Base::*Field,
    std::size_t Len
>
constexpr const foo<Base> s(char const (&section_name)[Len]) const {
    #pragma unused(section_name)
    return *this;
}

我的目标是能够简单地称呼它:

struct my_struct {
    std::map<std::string, int> section;
    constexpr auto bar = foo<my_struct>()
        .s<&my_struct::section>("hi");
};

也许是通过专业化?我无法围绕如何使此内容进行编译,因为目前我无法通过指针到成员,因为模板的地图类型在声明中首先出现,这使我在Clang上获得了以下内容:

注意:忽略候选模板:模板参数'map'

的无效明确指定参数

,我似乎也无法获得专业的神奇咒语:

template <auto FieldType, std::size_t Len>
constexpr const foo<Base> s(char const (&section_name)[Len]) const;
template <
    template <class, class> class Map,
    typename SecType,
    Map<std::string, SecType> Base::*Field,
    std::size_t Len
>
constexpr const foo<Base> s<Field, Len>(char const (&section_name)[Len]) const {
}

给出

错误:功能模板部分专业不允许

我还可以吗?值得一提的是C 14及以前的是可以的。

对于Pre-C 17解决方案,您可以将成员指针放入std::integral_constant。要确保地图的关键类型是std::string,请使用类型扣除来从指针获取成员类型,并将其密钥类型与std::string进行比较:

template<class T, class C>
T get_member_type(T C::*);
template<class Base>
struct foo{
  template<class I, std::size_t Len>
  constexpr const foo<Base> s(I, char const (&section_name)[Len]) const {
    using M=decltype(get_member_type(I::value));
    static_assert(std::is_same<typename M::key_type, std::string>{});
    return *this;
  }
};
#define CONST(e) std::integral_constant<decltype(e), e>
struct my_struct {
  std::map<std::string, int> section;
  constexpr static auto bar = foo<my_struct>().s(CONST(&my_struct::section){}, "hi");
};

您在编辑中遇到的错误是由于您无法部分专业化功能模板。幸运的是,您可以在上面的答案中扩展代码,以便您可以根据键类型过载标签:

template<class Base>
struct foo{
  template<class M>
  using get_key_type = typename M::key_type;
  template<class I>
  using get_member_type = decltype(::get_member_type(I::value));
  template<class I, std::size_t Len>
  constexpr auto s(I, char const (&section_name)[Len]) const {
    return s(I{}, section_name, 
      std::is_same<get_key_type<get_member_type<I>>, std::string>{}
    );
  }
private:
  template<class I, std::size_t Len>
  constexpr const auto s(I, char const (&section_name)[Len], std::false_type) const {
    return *this;
  }
  template<class I, std::size_t Len>
  constexpr const auto s(I, char const (&section_name)[Len], std::true_type) const {
    return *this;
  }
};

最新更新