【问题标题】:C++ templates, use of enable_if for two different implementation of an operatorC++ 模板,将 enable_if 用于运算符的两种不同实现
【发布时间】:2016-12-01 11:10:04
【问题描述】:

在我的代码中的某个时刻,我有这样的重载

template<int L>
template<int M>
inline StaticMemory<L>& StaticMemory<L>::operator =(const StaticMemory<M>& _m)
{
   if (this != &_m) { //Problem here!
      set_ui(this->mem, _m.mem, L, M);
   }
   return *this;
}

发生的情况是我突出显示的检查基本上是错误的,因为当L != M 指针比较无效时,除非我强制转换它。 我可能可以转换指针,但是有没有办法使用std::enable_if 来编写这样的运算符的两个不同版本?

谢谢

【问题讨论】:

  • 你在问什么?你是在问是否可以为L == M 编写一个版本的函数,为L != M 编写另一个版本的函数?
  • 是的,这就是我要问的。
  • 调用M == L 并不像看起来那么简单。只有显式调用才会这样做:l1-&gt;operator=&lt;L&gt;(l2); 否则将调用复制分配。
  • 我不明白,L == M 的情况会正确重载赋值运算符吗?
  • @user8469759:M == L 的情况很特殊,因为它与 copy assignment(不是 template相似 >)。当您提供StaticMemory&lt;L&gt; 时,将进行复制分配。这就是为什么std::enable_if 的解决方案(或具有专业化的解决方案)不能解决您的问题,您必须直接提供复制分配

标签: c++ c++11 templates typetraits


【解决方案1】:

我想,不用std::enable_if也是可以解决的

只需像这样写额外的operator=

template<int L>
inline StaticMemory<L>& StaticMemory<L>::operator =(const StaticMemory<L>& _m)
{
    if (this != &_m) { //There are no problem here!
        set_ui(this->mem, _m.mem, L, L);
    }
    return *this;
}

如果StaticMemory 模板参数相同,这将起作用。

如果它们不同,您的示例代码应该可以工作,您可以在其中投射任何您想要的东西

编辑:正确性证明:

#include <iostream>
template <int I>
struct Temp {
    template <int L>
    void operator=(const Temp<L>&) {
        std::cout << "Called with L\n";
    }
    void operator=(const Temp<I>&) {
        std::cout << "Called with I\n";  
    }
};

int main() {
    Temp<1> t1;
    Temp<2> t2;
    t1 = t1;
    t1 = t2;
}

这里的输出是:

Called with I
Called with L

【讨论】:

  • 对不起,我有一个问题,你建议同时实现它们吗?不会有一些冲突吗?因为当 M = L 时,编译器会生成哪一个?
  • @user8469759 是的,我建议同时实现它们。应该没有冲突,如果 M == L,我的模板将被调用,如果 M != L - 你的。
  • @user8469759 添加,证明
  • @Starl1ght 我相信关键是他不想测试这些值是否相等。他希望编译器为他做这件事。
  • 呃,是的,你是对的......我现在显然需要醒来。
【解决方案2】:

以下不作为复制作业

template <int L>
template <int M>
Temp<L>& Temp<L>::operator=(const Temp<M>&);

复制分配只是

template <int L>
Temp<L>& Temp<L>::operator=(const Temp<L>&);

所以是的,你必须在你的情况下编写这两个重载。

调用相同类型的模板赋值(第一次重载)的方式是显式调用,类似于:

this->operator=<L>(rhs);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-08
    • 2014-12-07
    • 2011-05-23
    • 1970-01-01
    • 2013-03-29
    • 2017-05-03
    • 1970-01-01
    相关资源
    最近更新 更多