将constexpr数组扩展为一组非类型模板参数

时间:2017-11-13 11:45:25

标签: c++ templates variadic-templates template-meta-programming constexpr

假设我有一个编译时constexpr数组和一个可变参数类模板,其中包含一组与数组元素相同类型的非类型参数。

我的目标是使用数组中的值实例化类模板:

struct Container
{
    int containee[3];
};

constexpr Container makeContainer();

template <int... Elements> class Foo;

Foo<makeContainer().containee[0],
    makeContainer().containee[1],
    makeContainer().containee[2]> foo;

以上代码效果很好。但是,每当我需要实例化Foo模板时,我都不得不手动索引数组。我想编译器自动为我做这件事:

Foo<Magic(makeContainer().containee)> foo;

我在cppreference做了一些RTFM,但这没有帮助。我知道std::forward<>(),但它不能应用于模板参数列表。

1 个答案:

答案 0 :(得分:7)

  1. 使用makeContainerstruct lambda (C ++ 17)constexpr operator()更改为constexpr。函数指针在这里不起作用。

    struct makeContainer
    {
        constexpr auto operator()() const
        {
            return Container{/* ... */};
        }
    };
    
  2. 使用std::make_index_sequencestd::index_sequence生成索引的编译时序列:

    template <typename C>
    constexpr auto fooFromContainer(const C& container)
    {
        return fooFromContainerImpl(container, std::make_index_sequence<3>{});
    }
    
  3. 通过constexpr创建一个新的C容器实例,然后展开序列以索引常量表达式中的元素:

    template <typename C, std::size_t... Is>
    constexpr auto fooFromContainerImpl(const C& container, std::index_sequence<Is...>)
    {
        constexpr auto c = container();
        return Foo<c.containee[Is]...>{};
    }
    
  4. complete example on wandbox.org

    只是为了好玩,这是一个C ++ 20实现:

    struct container { int _data[3]; };
    
    template <int... Is> 
    struct foo 
    { 
        constexpr auto t() const { return std::tuple{Is...}; }
    };
    
    template <typename C>
    constexpr auto foo_from_container(const C& c)
    {
        return []<std::size_t... Is>(const auto& c, std::index_sequence<Is...>)
        {
            return foo<c()._data[Is]...>{};
        }(c, std::make_index_sequence<3>{});
    }
    
    int main()
    {
        constexpr auto r = foo_from_container([]{ return container{42, 43, 44}; });   
        static_assert(r.t() == std::tuple{42, 43, 44});
    }
    

    live example on wandbox.org