在C ++中,如何创建`std :: initializer_list< base *>`而不新建并且不分别声明各个元素? [英] In C++, how can I create a `std::initializer_list<base *>` without new and without declaring individual elements separately?

查看:80
本文介绍了在C ++中,如何创建`std :: initializer_list< base *>`而不新建并且不分别声明各个元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++中,您可以在文件范围内声明某些内容的数组:

In C++, you can declare an array of something at the file scope:

static foo a[] = { foo(), foo(), foo() };

单个foo对象具有静态存储空间(即,它们在运行时未分配).

The individual foo objects have static storage (i.e. they are not allocated at run-time).

如果我有一个由两个或多个派生类继承的基类,则由于切片,以下内容将编译但无法按预期工作:

If I had a base class inherited by two or more derived classes, the following would compile but not work as expected due to slicing:

static base a[] = { derived1(), derived2() };

像这样的事情不会导致切片的发生:

Something like this should not cause slicing to happen:

static derived1 d1;
static derived2 d2;
static base *a[] = { &d1, &d2 };

我的问题是:如何在不必将d1d2a分开声明的同时保持单个(指向)元素的静态存储的同时执行相同的操作?以下给出了临时使用地址"错误:

My question is: How can I do the same without having to declare d1 and d2 separately from a, and while keeping static storage for the individual (pointed-to) elements? The following gives a "taking address of temporary" error:

static base *a[] = { &derived1(), &derived2() };

也许可以定义constexpr可变参数模板函数?像这样:

Maybe it would be possible to define a constexpr variadic template function? Something like:

template<typename... Args>
constexpr std::initializer_list<base *> base_array(Args... args) {
    ...
}

那我可以写:

static base *a[] = base_ptr_array(derived1(), derived2());

也许这将具有相同的临时地址"问题,尽管我的想法是由于这是一个constexpr,因此其工作原理与上述{ foo(), foo(), foo() }类似(不会创建临时对象).

Maybe this would have the same "taking address of temporary" problem, though my idea was that since this is a constexpr it would work similarly to { foo(), foo(), foo() } above (which doesn't create temporaries).

推荐答案

您可以使用一些模板来避免声明这些静态变量:

You can use some template to avoid declaring those static variables:

#include <tuple>
#include <array>
#include <type_traits>
#include <utility>

template<class Base, class... Ts>
struct foo {
    foo()
        : foo(Ts{}..., std::index_sequence_for<Ts...>{})
    {}
    std::tuple<Ts...> deriveds;
    std::array<Base*, sizeof...(Ts)> arr;

private:
    template<std::size_t... Is>
    foo(Ts... ts, std::index_sequence<Is...>)
        : deriveds(ts...)
        , arr{ &std::get<Is>(deriveds)...}
    {}
};


// test 
#include <iostream>

struct A {
    virtual void show() const {
        std::cout << "A\n";
    }
    virtual ~A() = default;
};
struct B: public A
{
    void show() const override {
        std::cout << "B\n";
    }
};
struct C: public A
{
    void show() const override {
        std::cout << "C\n";
    }
}; 

foo<A, A, B, C> f;

int main() {
    for ( A *ptr : f.arr ) {
        ptr->show();
    }
}

这篇关于在C ++中,如何创建`std :: initializer_list&lt; base *&gt;`而不新建并且不分别声明各个元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆