我可以在没有结构实例的情况下使用`hana :: keys`吗?

时间:2016-12-04 02:46:11

标签: c++ boost struct c++14 boost-hana

hana::keys的{​​{3}}表示我可以在函数调用语法中使用它,例如hana::keys(s)其中s是符合概念hana::Struct的类的实例,它返回一系列关键对象。

相关函数hana::accessors返回一系列访问函数,可用于从结构实例中获取相应的成员。

hana::accessors documentation

hana::accessors(s)
hana::accessors<S>()

是合法的,constexpr函数在S = decltype(s)时返回相同的内容 - 与结构S对应的序列。

当我使用hana::keys尝试此语法时,出现错误。这是一个MCVE,改编自hana文档中的一个例子:

#include <boost/hana.hpp>
#include <boost/hana/define_struct.hpp>
#include <boost/hana/keys.hpp>
#include <iostream>
#include <string>

namespace hana = boost::hana;

struct Person {
    BOOST_HANA_DEFINE_STRUCT(Person,
        (std::string, name),
        (unsigned short, age)
    );
};


// Debug print a single structure

template <typename T>
void debug_print_field(const char * name, const T & value) {
  std::cout << "\t" << name << ": " << value << std::endl;
}


template <typename S>
void debug_print(const S & s) {
  std::cout << "{\n";

  hana::for_each(hana::keys<S>(), [&s] (auto key) {
    debug_print_field(hana::to<char const *>(key), hana::at_key(s, key));
  });

  std::cout << "}" << std::endl;
}

// Debug print compare two structures

int main() {
    Person john{"John", 30}, kevin{"Kevin", 20};

    debug_print(john);
    std::cout << std::endl;
    debug_print(kevin);
    std::cout << std::endl;
}
$ g++-6 -std=c++14 -I/home/chris/boost/boost_1_61_0/ main.cpp
main.cpp: In function ‘void debug_print(const S&)’:
main.cpp:28:30: error: expected primary-expression before ‘>’ token
   hana::for_each(hana::keys<S>(), [&s] (auto key) {
                              ^
main.cpp:28:32: error: expected primary-expression before ‘)’ token
   hana::for_each(hana::keys<S>(), [&s] (auto key) {
                                ^

使用hana::keys(s)时,它可以正常工作。

但在我的实际应用中,我没有结构的实例,它只是一个模板参数。

作为一个黑客,我做到了:

// Work around for `hana::keys`

template <typename S>
constexpr decltype(auto) get_hana_keys() {
  return decltype(hana::keys(std::declval<S>())){};
}

相信这是基于我对文档中描述的hana的实现细节的有限理解。 - hana::keys应该返回一系列编译时字符串,并且所有信息都包含在类型中,因此只需获取类型和默认构造它应该是等效的。

当我在我的MCVE中使用get_hana_keys<S>()时,它会编译并运行正常。

但是我不知道它是否真的正确,或者我所做的假设超出了文档允许我假设的范围。

我使用的是提升版1.61gcc 6.2.0

我想知道的是,

  • hana::keys<S>()不起作用或这仅仅是一种疏忽是否有充分的理由? hana似乎设计得非常精心,所以我倾向于在这里猜测自己。

  • 我创建的黑客是否有任何问题或改进方法?

1 个答案:

答案 0 :(得分:2)

好问题!

  

hana::keys<S>()是否有效,或仅仅是疏忽?

hana::keys<S>()不起作用的原因是在一般情况下无法实现它。实际上,keys最初是为hana::map设计的,其中可能是有状态的,因此您确实需要一个对象来返回有意义的内容。不需要对象来检索hana::Struct的密钥这一事实只是巧合。

  

我创建的黑客是否有任何问题或改进方法?

从技术上讲,hana::string没有记录为默认构造,因此默认构造hana::tuple并不能保证其正常工作。但是,这是我在1eebdb修复的疏忽,所以你很好。

话虽如此,一个或许更惯用的解决方案如下:

template <typename S>
constexpr auto get_hana_keys() {
  return hana::transform(hana::accessors<S>(), hana::first);
}

事实上,这就是我们为hana::keys s定义hana::Struct的方式。

最后,请注意,与hana::Struct相关的所有内容都会通过语言级反映得到更好的效果,因此请原谅Hana提供的反思的古怪支持。没有语言支持,在这方面做任何好事都很难。