如何创建一个构造函数,让我可以使用花括号初始化列表进行构造?

发布于 2024-10-01 12:45:44 字数 640 浏览 8 评论 0原文

我有类 Phenotype 具有以下构造函数:

Phenotype(uint8 init[NUM_ITEMS]);

我可以创建这样的表型:

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

但是当我尝试创建这样的表型时出现错误:

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

输出:

$ 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*)

该错误似乎表明有一种方法可以定义一个构造函数,该构造函数需要一个大括号括起来的初始值设定项列表。有谁知道如何做到这一点?

I have class Phenotype with the following constructor:

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

幸福还没到 2024-10-08 12:45:44

它只能用于聚合(数组和某些类。与流行的看法相反,这也适用于许多非 Pod)。编写接受它们的构造函数是不可能的。

既然您将其标记为“C++0x”,那么这是可能的。神奇的词是“初始化列表构造函数”。然而

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

,这样的初始化将默认构造数组,然后使用赋值运算符。如果您的目标是速度和安全(由于太多的初始化程序,您会遇到编译时错误!),您还可以使用带有可变参数模板的普通构造函数。

不过,这可能比需要的更通用(通常一个初始化列表就完全足够了,特别是对于普通整数)。它受益于完美转发,因此可以将右值参数移动构造到数组元素中

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   

这是一个艰难的选择!

编辑更正,最后一个也可以,因为我们没有显式构造函数,所以它可以使用Phenotype的复制构造函数,构造一个临时 Phenotype 对象并将其复制到 p3。但这并不是我们真正希望的调用方式:)

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. The magic words is "initializer-list constructor". 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). 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. But that's not what we really would want the calls to be :)

多彩岁月 2024-10-08 12:45:44

在 C++0x 中,您似乎可以为此创建一个构造函数。我自己没有经验,但看起来它的名字是 初始化列表构造函数

容器可能会实现如下所示的初始化列表构造函数:

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 ...
};

In C++0x it seems you can create a constructor for this. I have no experience with it myself, but it looks like it's called 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 ...
};
哽咽笑 2024-10-08 12:45:44

您需要使用 std::initializer_list 模板类型。例子:

#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};
}

You need to use the std::initializer_list template type. 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};
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文