Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可变模板构造函数和移动构造函数_C++_C++11_Constructor_Variadic Templates_Template Meta Programming - Fatal编程技术网

C++ 可变模板构造函数和移动构造函数

C++ 可变模板构造函数和移动构造函数,c++,c++11,constructor,variadic-templates,template-meta-programming,C++,C++11,Constructor,Variadic Templates,Template Meta Programming,我有一个带有可变模板构造函数的模板类: template<typename T, int nb = 1> class MyClass { /* ... some stuff here ... */ template<typename... Ts> MyClass(Ts... ts) { /* ... some code ... */ } } 对于非模板构造函数,我通常做的是:构建一个MyClass类型的对象tmp,

我有一个带有可变模板构造函数的模板类:

template<typename T, int nb = 1>
class MyClass
{
 /* ... some stuff here ... */

    template<typename... Ts>
    MyClass(Ts... ts)
    {
         /* ... some code ... */
    }

}
对于非模板构造函数,我通常做的是:构建一个MyClass类型的对象
tmp
,我用
std::swap
将每个成员与
*this
交换,然后用
*this*
交换
源代码的每个成员。现在
tmp
包含了所有垃圾
*这个*
已经存在,我只是让构造函数的作用域负责删除
tmp


但是在这里我被卡住了,不知道如何构造我的
MyClass tmp(???)
对象。

问题是参数
Ts&&…
可以匹配
MyClass&
(即非常量)。这使得它在
auto b=a的情况下更匹配和类似(因为a不是常量)

因此,您必须使用一些SFNAE魔法禁用该案例,或者提供一个特定的重载来执行正确的操作:

#include <memory>
#include <string>
#include <iostream>

template<typename T, int nb = 1>
class MyClass
{
    /* ... some stuff here ... */

public:
    template<typename... Ts>
    MyClass(Ts&&... ts)
    : _pstr(std::make_shared<std::string>(std::forward<Ts>(ts)...))
    {
    }

    // match the specific case, and force a copy
    MyClass(MyClass<T, nb>& r)
    : MyClass(static_cast<const MyClass<T, nb>&>(r))
    {}

    // and now we must match all copy/move operations        
    MyClass(const MyClass<T, nb>&) = default;
    MyClass& operator=(const MyClass<T, nb>&) = default;
    MyClass(MyClass<T, nb>&&) = default;
    MyClass& operator=(MyClass<T, nb>&&) = default;

    void print() const {
        std::cout << *_pstr << std::endl;
    }
private:
    std::shared_ptr<std::string> _pstr;

};

// test
int main()
{
    auto a = MyClass<int>("hello, world");
    auto b = a;
    auto c = MyClass<int>("goodbye");
    auto d = c;
    b = c;
    a.print();
    b.print();
    c.print();
    d.print();
}
考虑使用C++17标记类型消除使用可变参数的构造函数的歧义。那么就没有必要像Richard的回答那样明确定义复制/移动构造函数

模板
类MyClass
{
/*…这里有些东西*/
模板
MyClass(标准::就地测试,测试…测试)
{
/*…一些代码*/
}
}
int main()
{
MyClass foo(标准:in_place,123456);
MyClass酒吧(foo);
}

如果您没有C++17,您可以轻松地将自己的
就地\u t
标记类型定义为空结构(但不在
std
命名空间中)。

简单,您几乎做到了:
MyClass(MyClass&&source)/*。。。这里还有一些东西*/有什么问题?变量构造函数与移动构造函数有什么关系?如何构建
tmp
对象?我不确定我应该在那里放多少论点。。。我是否应该根据
源代码的内部状态手动调用相应的构造函数?我如何调用构造函数来构建tmp,有多少个参数,属于哪种类型?@MCF:为什么要构建
tmp
对象?为什么你需要在你的移动构造器中进行这种复杂的舞蹈呢?您在
MyClass
中做了什么,使得移动构造函数的
=default
无法实现?对于每个数据成员,只需从源位置移动内容,如果无法从源位置复制,则从源位置复制。通常,默认的移动构造函数就足够了。如果需要实例化类的完整临时对象,那么使用move构造函数是没有意义的。
#include <memory>
#include <string>
#include <iostream>

template<typename T, int nb = 1>
class MyClass
{
    /* ... some stuff here ... */

public:
    template<typename... Ts>
    MyClass(Ts&&... ts)
    : _pstr(std::make_shared<std::string>(std::forward<Ts>(ts)...))
    {
    }

    // match the specific case, and force a copy
    MyClass(MyClass<T, nb>& r)
    : MyClass(static_cast<const MyClass<T, nb>&>(r))
    {}

    // and now we must match all copy/move operations        
    MyClass(const MyClass<T, nb>&) = default;
    MyClass& operator=(const MyClass<T, nb>&) = default;
    MyClass(MyClass<T, nb>&&) = default;
    MyClass& operator=(MyClass<T, nb>&&) = default;

    void print() const {
        std::cout << *_pstr << std::endl;
    }
private:
    std::shared_ptr<std::string> _pstr;

};

// test
int main()
{
    auto a = MyClass<int>("hello, world");
    auto b = a;
    auto c = MyClass<int>("goodbye");
    auto d = c;
    b = c;
    a.print();
    b.print();
    c.print();
    d.print();
}
hello, world
goodbye
goodbye
goodbye