这次主要学习的内容主要是C++ boost库中的 is_valid 函数,该函数 传入一个lambda表达式,通过判断该 lambda表达式 并返回一个可执行对象( UnnamedType类结构体的一个匿名对象),通过该可调用对象可以判断一个类型是否符合传入的 lambda表达式 中的内容,如:该类型是否含有 .serialize()成员函数 等等。
template<typename UnNameType>//is_valid调用后,UnNameType 为lambda匿名函数的类型
struct container {
private:
template<typename Param>
auto testValidity(int)-> decltype(declval<UnNameType>()(declval<Param>()), true_type()) {
// 因为 UnNameType 是 class lambda ,因此 declval<>()是创建一个表达式的lambda函数对象,传入的参数为Param的对象
// 最终其实还是利用lambda函数来检测 类型是否含有 .serialize这个成员
return true_type();
}//true_type() 重载 等同于true_type::value
template<typename Param>
constexpr auto testValidity(...) {
return false_type();
}
public:
template<typename Param>
constexpr auto operator() (const Param& obj){
cout << "operator():Param:" << typeid(Param).name() << endl;
return testValidity<Param>(int());
}
};
//传递lambda函数的方式有两种,1.利用模版进行传递 2.利用std::function<type (Param)> & obj
template<typename UnNameType>
constexpr auto is_valid(const UnNameType& obj) {
return container<UnNameType>();
//返回的是一个类型为container<UnNameType>的 类结构体的匿名对象 ,供后面的test调用operator()函数
}
auto hasserialize = is_valid([](auto&& obj) ->decltype(obj.serialize()) { return obj.serialize(); });
template<typename T>
auto serialize(T& obj)->typename enable_if< decltype(hasserialize(obj))::value ,string >::type{
return obj.serialize();
}
template<typename T>
auto serialize(T& obj)->typename enable_if< !decltype(hasserialize(obj))::value ,std::string >::type{
return to_string(obj);
}
void test_for_hana() {
A a;
B b;
C c;
auto test = is_valid([](const auto& t) -> decltype(t.serialize()) {});
std::cout << test(a) << std::endl;
std::cout << test(b) << std::endl;
std::cout << test(c) << std::endl;
// serialize 函数即是对 is_valid 函数的一层封装,通过判断是否存在serialize对象,并输出不同方式的序列化结果
std::cout << serialize(a) << std::endl;
std::cout << serialize(b) << std::endl;
std::cout << serialize(c) << std::endl;
}
enable_if 的使用:enable_if<A,B>::type 如果表达式 A 的值为 true 那么 enable_if<>::type的类型即为 表达式模板参数B的类型
is_valid函数 利用 class container 来进行 判断该类型是否含有某一成员函数,或者该类型是否符合某种使用方法。 class container 接受is_valid 传入的 class lambda 类型,在is_valid 中的 return container<UnNameType>(); 返回语句,在C++ 中遇到 A() 时,会在 返回A的临时匿名对象 和 返回 类型为A的无参函数之间 进行选择,如果不是前后语义进行限制的话,会有限选择返回 返回类型为A的无参函数,但是因为本题中后续 会将 is_valid 函数的返回值作为一个可调用的对象来进行使用,因此返回值是一个可执行对象(函数),而container 声明了operator()这么一个重载函数,意味着 container类对象 可以作为仿函数进行使用。
因此 ,is_valid 函数 接受一个lambda 对象, 返回一个验证 该lambda对象行为 的含有一个参数的可执行对象。(通俗来讲,is_valid 的返回值可以其参数<一个类型的对象> 的行为是否符合传入 is_valid 函数的lambda表达式的行为)