繁体   English   中英

从(const)推导的类型*用作模板函数template参数

[英]Deduced type from (const) *this used as template function template argument

我有简单的课程:

#include <utility>

template<class T, class... Ts>
T make(const Ts&... args) //generic class maker
{
    return T(args...);
}

template<class T>
class A
{
public:
    A(void)           : x_(T()), y_(T()) {}
    explicit A(int x) : x_(x), y_(x) {}
    A(int x, int y)   : x_(x), y_(y) {}
    A(const A& other) : x_(other.x_), y_(other.y_) {}
    A(A&& temp)       : x_(std::move(temp.x_)), y_(std::move(temp.y_)) {}

    auto& operator =(A other);
    auto& operator +=(const A& other);
    auto  operator + (const A& other) const;
private:
    T x_;
    T y_;
};

template<class T>
auto& A<T>::operator =(A<T> other)
{
    std::swap(*this, other); return *this;
}

template<class T>
auto& A<T>::operator+=(const A<T>& other)
{
    x_ += other.x_;
    y_ += other.y_;
    return *this;
}

template<class T>
auto A<T>::operator+(const A<T>& other) const
{
    return make<A<T>>(*this) += other;
}

int main()
{
    A<int> first(1);
    auto second = A<int>(2,2);
    auto third  = make<A<int>>(second+first);
    auto fourth = make<A<int>>(4);
    auto fifth  = make<A<int>>(5,5);
}

但是,当我尝试从* this推断出operator +类型时,我得到了一些我不期望的奇怪错误:

template<class T>
auto A<T>::operator+(const A<T>& other) const
{
    return make<typename std::remove_cv<decltype(*this)>::type>(*this) += other;
}

int main()
{
    auto solo = A<int>();
    solo + solo;
}

错误:

error: passing 'const A<int>' as 'this' argument of 'auto& A<T>::operator+=(const A<T>&) 
[with T = int]' discards qualifiers [-fpermissive]
     return make<typename std::remove_cv<decltype(*this)>::type>(*this) += other;
                                                                        ^
error: use of 'auto& A<T>::operator+=(const A<T>&) [with T = int]' before deduction 
of 'auto'
error: invalid use of 'auto'
     return make<typename std::remove_cv<decltype(*this)>::type>(*this) += other;
                                                                           ^
error: invalid use of 'auto'

如果我是对的,那么make(...)应该创建一个新对象(应该没有cv),那么为什么我会出现discards qualifiers [-fpermissive]错误?

问题是您要传递一个const对象作为operator+=的左手参数,它是一个非const成员。 为什么会这样呢?

让我们解析一下:

typename std::remove_cv<decltype(*this)>::type

this为一个const成员函数将是A<T> const* const 解引用使我们得到A<T> const& (而不是A<T> const !)。 但是引用没有cv-限定,因此remove_cv实际上不做任何事情。 结果,以上类型为:

A<T> const&

这根本不是您想要的。 您想要创建一个this的副本,而不是将const的引用绑定到this 我们需要做的就是删除参考。 有一个类型特征:

typename std::decay<decltype(*this)>::type

因此,您要做的是:

template<class T>
auto A<T>::operator+(const A<T>& other) const
{
    return make<std::decay_t<decltype(*this)>>(*this) += other;
}

但这太复杂了。 我更喜欢这样的东西:

template <class T>
class A {
    ...
    friend A<T> operator+(A lhs, A const& rhs) {
        lhs += rhs;
        return lhs;
    }
};

*this是一个表达式,因此当使用decltype进行查询时,它会产生一个左值引用类型,因此,将std::remove_cv特征应用于引用类型,而应将其应用于引用的类型:

return make<typename std::remove_cv<
              typename std::remove_reference<decltype(*this)>::type
           >::type>(*this) += other;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM