编写可变参数模板构造函数 [英] Writing variadic template constructor

查看:117
本文介绍了编写可变参数模板构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我问这个问题,但现在我想扩大它。我写了以下类:

Recently I asked this question but now I would like to expand it. I wrote the following class:

template <class T>
class X{
public:
    vector<T> v;
    template <class T>
    X(T n) {
        v.push_back(n);
    }
    template <class T, class... T2>
    X(T n, T2... rest) {
        v.push_back(n);
        X(rest...);
    }
};

使用

X<int> obj(1, 2, 3);  // obj.v containts only 1

向量只包含第一个值,我检查并看到构造函数被调用了3次,所以我可能创建temp对象和填充他们的向量与其余的参数。如何解决这个问题?

Vector only contains the first value, but not others. I've checked and saw that constructor is called 3 times, so I'm probably creating temp objects and filling their vectors with the rest of the arguments. How do I solve this problem?

推荐答案

首先,你的代码不能为我编译。

First, your code doesn't compile for me.

main.cpp:7:15: error: declaration of ‘class T’
     template <class T>
               ^
main.cpp:3:11: error:  shadows template parm ‘class T’
 template <class T>
           ^

我将外层更改为 U

template <class U>
class X{
public:
    vector<U> v;
    template <class T>
    X(T n) {
        v.push_back(n);
    }
    template <class T, class... T2>
    X(T n, T2... rest) {
        v.push_back(n);
        X(rest...);
    }
};

您确定这会导致您在问题详细资料中提出的问题...

You're correct that this causes the issue you gave in the question details...

X<int> obj(1, 2, 3);  // obj.v containts only 1

这是因为语句 X rest ...)在构造函数的末尾不会递归调用构造函数来继续初始化同一个对象;它会创建一个 X 对象,然后将其丢弃。一旦构造函数的 body 开始执行,就不再可能在同一个对象上调用另一个构造函数。委派必须发生在 ctor-initializer 中。例如,你可以这样做:

This is because the statement X(rest...) at the end of your constructor doesn't recursively call the constructor to continue initializing the same object; it creates a new X object and then throws it away. Once a constructor's body begins to execute, it's no longer possible to invoke another constructor on the same object. Delegation must occur in the ctor-initializer. So for example, you could do this:

template <class T, class... T2>
X(T n, T2... rest): X(rest...) {
    v.insert(v.begin(), n);
}

这很糟糕,因为在向量的开头插入效率不高。

That sucks though, because inserting at the beginning of a vector isn't efficient.

更好地采用 std :: initializer_list< T> 参数。这是 std :: vector 本身的作用。

Better to take a std::initializer_list<T> argument. This is what std::vector itself does.

X(std::initializer_list<U> il): v(il) {}
// ...
X<int> obj {1, 2, 3};

这篇关于编写可变参数模板构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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