首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模板化构造函数与模板化复制构造函数

模板化构造函数与模板化复制构造函数
EN

Stack Overflow用户
提问于 2010-12-12 06:42:11
回答 2查看 838关注 0票数 3

我有一个带有用于隐式移动转换的模板化构造函数的类,但是这个构造函数不应该用于该类(它应该只是可复制构造的)。但是,编译器总是尝试使用模板化的构造函数,而不是常规的复制构造函数。

例如,我得到了下面的编译器错误,link。(如果你想试一下,你可以直接复制粘贴这段代码)

代码语言:javascript
复制
struct implementation{};
class my_class
{
 my_class(my_class&&); // delete move-constructor... OUCH... COMPILER ERROR
public:
 my_class(){}
 my_class(const my_class& other) : impl_(other.impl_){}

 template<typename T>
 my_class(T&& impl) : impl_(std::make_shared<T>(std::move(impl))){} // Still tries to use this...

private:
 std::shared_ptr<implementation> impl_;
};

class other_class
{
public:
 my_class foo()
 { 
       return instance_; // Wants to use move-constructor???
 }
private:
 my_class instance_;
};

有人知道如何正确解决这个问题吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-12-12 06:49:33

好的,这是我对my_class的彻底改造

代码语言:javascript
复制
class my_class
{
public:
    my_class() {}
    my_class(my_class&& that) : impl_(std::move(that.impl_)) {}

    template <typename T> my_class(T&& impl,
    typename std::enable_if<
        std::is_base_of<
            implementation,
            typename std::remove_reference<T>::type
        >::value,
        void
    >::type* dummy = 0
    ) : impl_(std::make_shared<T>(std::forward<T>(impl))) {}

    template <typename T>
    typename std::enable_if<
        std::is_base_of<
            implementation,
            typename std::remove_reference<T>::type
        >::value,
        my_class&
    >::type
    operator=(T&& impl)
    {
        std::make_shared<implementation>(std::forward<T>(impl)).swap(impl_);
        return *this;
    }

private:
    std::shared_ptr<implementation> impl_;
};

正如其他人所建议的,通过使用std::forward而不是std::move,这适用于左值和右值引用。remove_reference是必需的,因为对于左值引用,T是引用,derived&不是从base派生的,但derived派生(注意引用)。

票数 4
EN

Stack Overflow用户

发布于 2010-12-12 09:12:11

这永远不会起作用:

代码语言:javascript
复制
template<typename T>
my_class(typename std::enable_if<std::is_base_of<implementation, derived_1>::value, T&&>::type impl) : impl_(std::make_shared<T>(std::move(impl)))  {}

template <typename T> 
my_class& operator= (typename std::enable_if<std::is_rvalue_reference<T&&>::value && !std::is_same<T, my_class>::value, T&&>::type impl)

原因是您只在非演绎的上下文中使用T。简单地说,如果编译器应该从中推导出的参数的形式是Anything<T>::type,那么它就不能推导出T

所以,如果你想在赋值运算符上使用enable_if,你可以把它放在返回值中:

代码语言:javascript
复制
template <class T>
typename enable_if<..., T&>::type operator=(const T&);

在转换(也应该适用于move )构造函数的情况下,添加一个带有默认值的伪参数:

代码语言:javascript
复制
template <class T>
MyClass(const T&, typename enable_if<..., void>::type* =0);

FredOverflow已经为您提供了正确的赋值运算符。

顺便说一句,如果您使用std::forward而不是std::move,则不必将其限制为右值引用。参见here。这将为您提供(从FredOverflow复制和粘贴):

代码语言:javascript
复制
template <typename T>
typename std::enable_if<std::is_base_of<implementation, T>::value, my_class&>::type
operator=(T&& impl)
{
    std::make_shared<implementation>(std::forward<T>(impl)).swap(impl_);
    return *this;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4419375

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档