简体   繁体   English

括号括起的初始化程序列表构造函数

[英]Brace-enclosed initializer list constructor

I have class Phenotype with the following constructor: 我有以下构造函数的类Phenotype:

Phenotype(uint8 init[NUM_ITEMS]);

I can create a Phenotype like this: 我可以创建这样的表型:

uint8 data[] = {0,0,0,0,0};
Phenotype p(data);

But I get an error when I try to create one like this: 但是当我尝试创建一个这样的错误消息:

Phenotype p = {0,0,0,0,0};

Output: 输出:

$ make
g++ -Wall -g main.cpp -std=c++0x
main.cpp: In function ‘int main(int, char**)’:
main.cpp:109: error: no matching function for call to ‘Phenotype::Phenotype(<brace-enclosed initializer list>)’
main.cpp:37: note: candidates are: Phenotype::Phenotype(uint8*)

The error seems to indicate that there is a way to define a constructor which takes a brace-enclosed initializer list. 该错误似乎表明存在一种定义带括号括起的初始化程序列表的构造函数的方法。 Does anyone know how this might be done? 有谁知道该怎么做?

It can only be done for aggregates (arrays and certain classes. Contrary to popular belief, this works for many nonpods too). 只能对聚合(数组和某些类。与流行的看法相反,这也适用于许多非荚)。 Writing a constructor that takes them is not possible. 编写带它们的构造函数是不可能的。

Since you tagged it as "C++0x", then this is possible though. 由于您将其标记为“ C ++ 0x”,因此这是可能的。 The magic words is "initializer-list constructor". 神奇的词是“ initializer-list构造函数”。 This goes like 这就像

Phenotype(std::initializer_list<uint8> c) {
  assert(c.size() <= std::size(m_array));
  std::copy(c.begin(), c.end(), m_array);
}

// used like
Phenotype p1{1, 2, 3};
Phenotype p2({1, 3, 2}); // works too
Phenotype p3(1, 2, 3); // doesn't work

However, such initialization will default construct the array and then use the assignment operator. 但是,此类初始化将默认构造数组,然后使用赋值运算符。 If you aim for speed and safety (you get compile time errors for too many initializers!), you can also use an ordinary constructor with a variadic template. 如果您追求速度和安全性(太多初始化器会导致编译时错误!),那么您也可以将普通构造函数与可变参数模板一起使用。

This can be more generic than needed though (often an initializer_list completely suffices, especially for plain integers). 不过,这可能比需要的通用(通常initializer_list完全足够,特别是对于纯整数)。 It benefits from perfect forwarding, so that an rvalue argument can be move constructed into an array element 它得益于完美的转发,因此可以将右值参数移动到数组元素中

template<typename ...T>
Phenotype(T&&...t):m_array{ std::forward<T>(t)... } {

}

// used like
Phenotype p1{1, 2, 3}; 
Phenotype p2(1, 2, 3); // works too
Phenotype p3({1, 2, 3}); // doesn't work   

It's a hard choice! 这是一个艰难的选择!

Edit Correction, the last one works too, as we didn't make the constructor explicit , so it can use the copy constructor of Phenotype , constructing a temporary Phenotype object and copy it over to p3 . 编辑更正,最后一个也可以,因为我们没有使构造函数explicit ,因此它可以使用Phenotype的copy构造函数,构造一个临时Phenotype对象并将其复制到p3 But that's not what we really would want the calls to be :) 但这不是我们真正希望的电话:)

In C++0x it seems you can create a constructor for this. 在C ++ 0x中,您似乎可以为此创建一个构造函数。 I have no experience with it myself, but it looks like it's called initializer list-constructor . 我自己对此没有经验,但是看起来它像称为Initializer list-constructor

A container might implement an initializer-list constructor like this: 容器可以实现如下的初始化列表构造函数:

template<class E> class vector {
public:
    vector (std::initializer_list<E> s) // initializer-list constructor
    {
        reserve(s.size());  // get the right amount of space
        uninitialized_copy(s.begin(), s.end(), elem);   // initialize elements (in elem[0:s.size()))
        sz = s.size();  // set vector size
    }

    // ... as before ...
};

You need to use the std::initializer_list template type. 您需要使用std :: initializer_list模板类型。 Example: 例:

#include <iostream>
class X {
    public:
        X (std::initializer_list<int> list) {
        for (auto i = list.begin(); i != list.end(); i++) {
                std::cout << *i << std::endl;
            }
        }
};


int main () {
    X x = {1,2,3,4,5};
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM