【问题标题】:Initialize boost::hana::tuple with one argument用一个参数初始化 boost::hana::tuple
【发布时间】:2017-02-15 11:41:33
【问题描述】:

假设我们有这样的东西:某个类 Foo ('FooInterface') 的接口和一个容器类 Bar,其中包含来自 'FooInterface' 的派生类。

现在我将派生类 ('FooOne', 'FooTwo') 的类型列表转发给容器类,并将它们的实例存储在 'boost::hana::tuple' 后面的一个小类型计算('FooTuple')。

现在如何根据 'FooList' 的大小使用取消引用的 this 指针初始化元组元素?

MCVE (Wandbox)

#include <iostream>

#include <boost/hana.hpp>

namespace hana = boost::hana;

template <typename FooList>
class Bar;

template <typename FooList>
class FooInterface
{
public:
    FooInterface(Bar<FooList>& bar) {}

public:
    virtual void foo() = 0;
};

class FooOne;
class FooTwo;

using MyFooList = decltype(hana::tuple_t<FooOne, FooTwo>);

class FooOne final
    : public FooInterface<MyFooList>
{
public:
    FooOne(Bar<MyFooList>& bar) 
        : FooInterface(bar)
    {}

public:
    void foo() override
    {
        std::cout << "FooOne!\n";
    }
};

class FooTwo final
    : public FooInterface<MyFooList>
{
public:
    FooTwo(Bar<MyFooList>& bar) 
        : FooInterface(bar)
    {}

public:
    void foo() override
    {
        std::cout << "FooTwo!\n";
    }
};

template <typename FooList>
class Bar
{
public:
    using FooTuple = typename decltype(hana::unpack(FooList(), hana::template_<hana::tuple>))::type;

    FooTuple foos{ *this, *this };
};

int main() 
{
   Bar<MyFooList> b;
   b.foos[hana::int_c<0>].foo();
   b.foos[hana::int_c<1>].foo();
}

输出:

FooOne!
FooTwo!

【问题讨论】:

    标签: c++ boost template-meta-programming generic-programming boost-hana


    【解决方案1】:

    hana::replicate 是你的朋友。

    template <typename FooList>
    class Bar {
        ...
    
        using FooTuple = ...;
        FooTuple foos;
    
        Bar() : foos(hana::replicate<hana::tuple_tag>(*this, hana::size_c<N>)) {}
    };
    

    现在,您必须小心,因为在 replicate 中创建元组时会复制每个 *this。如果您想要引用,请像这样使用reference_wrapper

    foos(hana::replicate<hana::tuple_tag>(std::ref(*this), hana::size_c<N>))
    

    然后确保FooTuple 中每个事物的构造函数都可以从reference_wrapper 构造(如果它们采用引用就是这种情况)。

    【讨论】:

    • hana 总是让我惊叹:)
    【解决方案2】:

    不确定这是否是最简单的方法 - 但您可以尝试 std::index_sequence 这样做:

    template <typename FooList>
    class Bar
    {
        static constexpr size_t fooListSize = decltype(hana::size(std::declval<FooList>()))::value;
        template <std::size_t ...I>
        Bar(std::index_sequence<I...>) : foos{(I, *this)...} {}
    
    public:
        using FooTuple = typename decltype(hana::unpack(FooList(), hana::template_<hana::tuple>))::type;
    
        Bar() : Bar(std::make_index_sequence<fooListSize>{}) {}
    
        FooTuple foos;
    };
    

    【讨论】:

    • 我总是忘记逗号操作符
    • 人们总是忘记hana::replicate :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    相关资源
    最近更新 更多