加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 抽象类为std :: initializer_list对象

发布时间:2020-12-16 09:56:37 所属栏目:百科 来源:网络整理
导读:为了获得更清晰的语法,我想使用std :: initializer_list将对象列表发送到构造函数.然而,这些对象是抽象的,这会导致一个问题:在VS 2013中,它丢失了vfptr引用,给出了“R6025:纯虚函数调用”运行时错误,而且它抱怨它“无法分配一个抽象对象”在编译期间输入“
为了获得更清晰的语法,我想使用std :: initializer_list将对象列表发送到构造函数.然而,这些对象是抽象的,这会导致一个问题:在VS 2013中,它丢失了vfptr引用,给出了“R6025:纯虚函数调用”运行时错误,而且它抱怨它“无法分配一个抽象对象”在编译期间输入“base”.我猜测编译器试图复制对象(这是不可取的 – 它们可能很大),但仅成功复制基类,因此错误.我的问题是:是否有一个解决方案:(1)避免复制对象和(2)不是大量冗长,否定“更清晰的语法”优势?下面的代码说明了我的问题:

#include <cstdio>
#include <initializer_list>

struct base{
    virtual void foo() const = 0;
};

struct derived : public base{
    int i;
    derived(int i) : i(i) {}
    void foo() const{
        printf("bar %i",i);
    }
};

void foo_everything(const std::initializer_list<base> &list){
    for (auto i = list.begin(),iend = list.end(); i != iend; i++) i->foo();
}

int main(void){

    // Works fine
    derived d(0);
    base * base_ptr = &d;
    base_ptr->foo();    

    // Does not work fine
    foo_everything({ derived(1),derived(2),derived(3) });
}

请注意,使用base&在模板错误中,因为std :: initializer_list尝试“[形成一个]指向引用类型base&”的指针,并且在使用base *时,然后获取每个派生类的地址确实在实际工作,它通过采取临时的地址,因此不安全(g抱怨).如果我在方法调用之外声明派生类(我的临时解决方案),后者确实有效,但它仍然比我希望的更冗长.

解决方法

使用initializer_list< base *>的一些hackish方法:

template<class... Ts>
void foo_everything(Ts&&... args){
    std::initializer_list<base *> list = {&args...};
    for(auto i : list) i->foo();
}

然后从通话中删除大括号:

foo_everything(derived(1),derived(3));

如果你真的不需要转换为base *并执行虚拟调用,并且只想在传入的每个对象上调用foo(),那么我们可以使用通常的pack-expansion-inside-an-initializer-list技巧:

template<class... Ts>
void foo_everything(Ts&&... args){
    using expander = int[];
    (void) expander { 0,((void) std::forward<Ts>(args).foo(),0)...};
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读