在C ++中,如何创建`std :: initializer_list< base *>`而不新建并且不分别声明各个元素? [英] In C++, how can I create a `std::initializer_list<base *>` without new and without declaring individual elements separately?
问题描述
在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 };
我的问题是:如何在不必将d1
和d2
与a
分开声明的同时保持单个(指向)元素的静态存储的同时执行相同的操作?以下给出了临时使用地址"错误:
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< base *>`而不新建并且不分别声明各个元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!