我应该使用()或{}转发参数? [英] Should I use () or {} when forwarding arguments?

查看:145
本文介绍了我应该使用()或{}转发参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下类:

struct foo
{
    std::size_t _size;
    int* data;
public:
    explicit foo(std::size_t s) : _size(s) { }
    foo(std::size_t s, int v)
        : _size(s)
    {
        data = new int[_size];
        std::fill(&data[0], &data[0] + _size, v);
    }

    foo(std::initializer_list<int> d)
        : _size(d.size())
    {
        data = new int[_size];
        std::copy(d.begin(), d.end(), &data[0]);
    }

    ~foo() { delete[] data; }

    std::size_t size() const { return _size; }
};

我想像这样转发参数:

template <typename... Args>
auto forward_args(Args&&... args)
{
    return foo{std::forward<Args>(args)...}.size();
    //--------^---------------------------^
}

std::cout << forward_args(1, 2) << " " << forward_args(1) << " " 
          << forward_args(2) << "\n";

如果用 {} c $ c>()输出 1 1 2 而不是 2 1 1

If I replace {} with () the output is 1 1 2 instead of 2 1 1.

这对我的班级最有意义?

Which would make the most sense for my class?

推荐答案

{} ()的使用决定了调用哪个构造函数。

The use of {} vs. () determines which constructor is called.


  • {} 会调用 foo(std :: initializer_list&

  • The {} will call the form foo(std::initializer_list<int> d) and you get the results you seem to expect.

()

哪种形式取决于您希望 forward_args 方法支持的语义。如果你想让参数按原样传递,那么应该使用()(在这种情况下,用户需要提供

Which form to favour depends on what semantics you want the forward_args method to support. If you want the parameters to be passed "as is", then the () should be used (in this case the user will need to provide an initialiser_list as an argument to begin with).

可能(可能)您希望支持的表单是()并使用如下;

Possibly (probably) the form you wish to favour is () and used as follows;

template <typename... Args>
auto forward_args(Args&&... args)
{
    return foo(std::forward<Args>(args)...).size();
    //--------^---------------------------^
}

int main()
{
    std::cout << forward_args(std::initializer_list<int>{1, 2}) << " "
              << forward_args(std::initializer_list<int>{3}) << " " 
              << forward_args(std::initializer_list<int>{4}) << "\n";
}

initializer_list cppreference页面

Side note; the cppreference page on the initializer_list has a good example of this behaviour.

如果需要(即支持 forward_args({1,2})),您可以为 initializer_list 提供重载;

If desired (i.e. to support forward_args({1,2})), you can provide an overload for initializer_list;

template <class Arg>
auto forward_args(std::initializer_list<Arg> arg)
{
    return foo(std::move(arg)).size();
}






initializer_list ,类构造函数最终是混淆的来源,这在对象构造过程中呈现。 foo(1,2) foo {1,2} 之间有区别;后者调用构造函数的 initializer_list 形式。解决这一问题的一种技术是使用标签来区分正常构造函数形式与 initializer_list 表单。


As noted: given the initializer_list, the class constructors are ultimately the source of the confusion, and this presents itself during the object construction. There is a difference between foo(1,2) and foo{1,2}; the latter calls the initializer_list form of the constructor. One technique to resolve this is to use a "tag" to differentiate the "normal" constructor forms from the initializer_list form.

这篇关于我应该使用()或{}转发参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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