【问题标题】:using boost::hana for introspection使用 boost::hana 进行自省
【发布时间】:2023-03-23 15:19:02
【问题描述】:

我正在浏览很棒的 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()”。

注意:检查 objstatic_assert(has_toString(obj), "Does not implement toString()."); 显示正确的行为。

我错过了什么吗?还是编译器(clang 5.0.1)或库(boost 1.66)问题?

谢谢。

【问题讨论】:

    标签: c++ boost boost-hana


    【解决方案1】:

    您的optionalToStringX 函数采用T const&amp;toString 不是 const 限定的成员函数,因此不适用。

    Live On Coliru

    #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
    

    【讨论】:

    • @Wum 老实说,我没有“看到”它,我只是通过修补“找到”它。让我看到的是(在直接测试has_toString 之后,您仍然可以在示例中看到)只需将has_toString(obj) 替换为std::true_type{},如下所示:error: passing 'const WithToString' as 'this' argument discards qualifiers。也许这个技巧下次会对你有所帮助:)
    猜你喜欢
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多