使用 boost::hana 进行内省
using boost::hana for introspection
我正在浏览很棒的 boost::hana 库的帮助页面的示例,但无法使内省示例正常工作。
这段代码的目的是在编译时检查一个对象是否有特定的成员函数,然后使用这个成员函数或做一些默认的事情。
所以我声明了这两种类型:
struct WithoutToString
{ };
struct WithToString
{
std::string toString()
{
return "implements toString()";
}
};
这是使用 hana::is_valid
进行检查的第一个版本:
auto has_toString = hana::is_valid([] (auto&& obj) -> decltype(obj.toString()) { });
template <typename T>
std::string optionalToString1(T const& obj)
{
return hana::if_(has_toString(obj),
[] (auto& x) { return x.toString(); },
[] (auto& x) { return "toString not defined"; }
)(obj);
}
这是使用 hana::sfinae
:
检查的第二个版本
template <typename T>
std::string optionalToString2(T const& obj)
{
auto maybeToString = hana::sfinae([](auto&& x) -> decltype(x.toString())
{
return x.toString();
});
return maybeToString(obj).value_or("toString not defined");
}
像这样使用两个版本...
int main()
{
WithToString obj;
std::cout << optionalToString1(obj);
std::cout << optionalToString2(obj);
return 0;
}
...始终显示 "toString not defined" 而不是 "implements toString()"。
注意:用 static_assert(has_toString(obj), "Does not implement toString().");
检查 obj
显示正确的行为。
我错过了什么吗?还是编译器 (clang 5.0.1) 或库 (boost 1.66) 问题?
谢谢。
您的 optionalToStringX
函数需要 T const&
。 toString
不是 const-qualified 成员函数,因此不适用。
#include <boost/hana.hpp>
#include <string>
namespace hana = boost::hana;
struct WithoutToString { };
struct WithToString { std::string toString() const { return "implements toString()"; } };
namespace v1 {
//This is the 1st version of the check using hana::is_valid:
auto has_toString = hana::is_valid([] (auto&& obj) -> decltype(obj.toString()) { });
template <typename T>
std::string optionalToString1(T const& obj)
{
return hana::if_(has_toString(obj),
[] (auto&& x) { return std::forward<decltype(x)>(x).toString(); },
[] (auto&&) { return "toString not defined"; }
)(obj);
}
}
namespace v2 {
//This is the 2nd version of the check using hana::sfinae:
template <typename T>
std::string optionalToString2(T const& obj)
{
auto maybeToString = hana::sfinae([](auto&& x) -> decltype(x.toString())
{
return x.toString();
});
return maybeToString(obj).value_or("toString not defined");
}
}
#include <iostream>
int main()
{
WithToString with;
WithoutToString without;
std::cout << std::boolalpha << v1::has_toString(without) << std::endl;
std::cout << std::boolalpha << v1::has_toString(with) << std::endl;
std::cout << v1::optionalToString1(without) << std::endl;
std::cout << v1::optionalToString1(with) << std::endl;
std::cout << v2::optionalToString2(without) << std::endl;
std::cout << v2::optionalToString2(with) << std::endl;
}
版画
true
false
implements toString()
toString not defined
implements toString()
toString not defined
我正在浏览很棒的 boost::hana 库的帮助页面的示例,但无法使内省示例正常工作。
这段代码的目的是在编译时检查一个对象是否有特定的成员函数,然后使用这个成员函数或做一些默认的事情。
所以我声明了这两种类型:
struct WithoutToString
{ };
struct WithToString
{
std::string toString()
{
return "implements toString()";
}
};
这是使用 hana::is_valid
进行检查的第一个版本:
auto has_toString = hana::is_valid([] (auto&& obj) -> decltype(obj.toString()) { });
template <typename T>
std::string optionalToString1(T const& obj)
{
return hana::if_(has_toString(obj),
[] (auto& x) { return x.toString(); },
[] (auto& x) { return "toString not defined"; }
)(obj);
}
这是使用 hana::sfinae
:
template <typename T>
std::string optionalToString2(T const& obj)
{
auto maybeToString = hana::sfinae([](auto&& x) -> decltype(x.toString())
{
return x.toString();
});
return maybeToString(obj).value_or("toString not defined");
}
像这样使用两个版本...
int main()
{
WithToString obj;
std::cout << optionalToString1(obj);
std::cout << optionalToString2(obj);
return 0;
}
...始终显示 "toString not defined" 而不是 "implements toString()"。
注意:用 static_assert(has_toString(obj), "Does not implement toString().");
检查 obj
显示正确的行为。
我错过了什么吗?还是编译器 (clang 5.0.1) 或库 (boost 1.66) 问题?
谢谢。
您的 optionalToStringX
函数需要 T const&
。 toString
不是 const-qualified 成员函数,因此不适用。
#include <boost/hana.hpp>
#include <string>
namespace hana = boost::hana;
struct WithoutToString { };
struct WithToString { std::string toString() const { return "implements toString()"; } };
namespace v1 {
//This is the 1st version of the check using hana::is_valid:
auto has_toString = hana::is_valid([] (auto&& obj) -> decltype(obj.toString()) { });
template <typename T>
std::string optionalToString1(T const& obj)
{
return hana::if_(has_toString(obj),
[] (auto&& x) { return std::forward<decltype(x)>(x).toString(); },
[] (auto&&) { return "toString not defined"; }
)(obj);
}
}
namespace v2 {
//This is the 2nd version of the check using hana::sfinae:
template <typename T>
std::string optionalToString2(T const& obj)
{
auto maybeToString = hana::sfinae([](auto&& x) -> decltype(x.toString())
{
return x.toString();
});
return maybeToString(obj).value_or("toString not defined");
}
}
#include <iostream>
int main()
{
WithToString with;
WithoutToString without;
std::cout << std::boolalpha << v1::has_toString(without) << std::endl;
std::cout << std::boolalpha << v1::has_toString(with) << std::endl;
std::cout << v1::optionalToString1(without) << std::endl;
std::cout << v1::optionalToString1(with) << std::endl;
std::cout << v2::optionalToString2(without) << std::endl;
std::cout << v2::optionalToString2(with) << std::endl;
}
版画
true
false
implements toString()
toString not defined
implements toString()
toString not defined