【问题标题】:How can I define a template operator inside a template class scope?如何在模板类范围内定义模板运算符?
【发布时间】:2021-03-31 19:34:51
【问题描述】:

我尝试“模板化”的矩阵类有问题。这个想法是能够在不显式重载乘法方法的情况下将两个不同类型的矩阵相乘。例如,假设我们有一个type A 和一个type B。如果我将matrix<A> 乘以matrix<B>,并且如果我知道将元素相乘type A * type B 给我一个type B,那么matrix<A>*matrix<B> 应该给我一个matrix<B>(我希望它很清楚)。

话虽如此,我用std::common_type 部分解决了我的问题。在我尝试实现 *= 运算符之前,我的代码表现良好(你会看到你是否评论了 *= 相关部分)。这是一个简单的代码,可以重现我当前的错误:

#ifndef MATRICE_H
#define MATRICE_H

#include <typeinfo>
#include <type_traits>
#include <iostream>

template<typename T1>
class Matrice
{
private:
    T1 table;

public:
    T1 getTable(){return table;}
    Matrice(T1 m_table);

    //template<typename T2>
    //Matrice<T1>& operator *= (Matrice<T2>&);
};

template<typename T1, typename T2, typename T3>
Matrice<T3> operator*(Matrice<T2>&, Matrice<T1>&);

template<typename T1, typename T2>
Matrice<T1>& Matrice<T1>::operator *= (const Matrice<T2>& B);

#endif

和身体:

#include "Matrice.h"

template<typename T1>
Matrice<T1>::Matrice(T1 m_table):table(m_table)
{
}

template<typename T1, typename T2>
Matrice<typename std::common_type<T1,T2>::type> operator * (Matrice<T2>& M2, Matrice<T1>& M1)
{   
    
    typename std::common_type<T1,T2>::type tab3= (M1.getTable())*(M2.getTable());
    return Matrice<typename std::common_type<T1,T2>::type>(tab3);
}

template<typename T1, typename T2>
Matrice<T1>& Matrice<T1>::operator *= (const Matrice<T2>& B)
{
    table = (typename T1) table*(B.getTable())
}

int main()
{
    float tab1(12.5);
    int tab2(11);
    Matrice<float> M1(tab1);
    Matrice<int> M2(tab2);
    Matrice<float> M3 =  M1*M2;
    std::cout << M3.getTable() << std::endl;
    M3*=M2;
    return 0;
}

我收到以下镜像错误,感觉就像 c++ 之神在四处游荡:

Matrice.h:26:6: error: no declaration matches 'void Matrice<T1>::operator*=(Matrice<T2>&)'
   26 | void Matrice<T1>::operator *= (Matrice<T2>& B);

Matrice.cpp:18:6: error: no declaration matches 'void Matrice<T1>::operator*=(Matrice<T2>&)'
   18 | void Matrice<T1>::operator *= (Matrice<T2>& B)

和显而易见的

Matrice.cpp: In function 'int main()':
Matrice.cpp:31:7: error: no match for 'operator*=' (operand types are 'Matrice<float>' and 'Matrice<int>')
   31 |     M3*=M2;

备注:我已经尝试寻找这些错误,我只看到了一些我不太了解的模糊相关的东西。例如这里:Define a template function taking a parameter of a template class 请温柔,这是我的第一次模板冒险!

附加问题:是 typename std::common_type::type 每次出现在代码中时都会进行评估,还是以某种方式记住了结果?我可能会乘以大型矩阵,并且我想避免评估 typename std::common_type::type 数千次以获得恒定结果。

编辑:这里提供的示例只是重现错误的最小代码

EDIT2:类定义中的注释运算符 *= 只是我迄今为止为规避错误所做的各种尝试的痕迹

【问题讨论】:

  • 您注释掉的operator*= 返回一个Matrice&lt;T1&gt;&amp;,而您定义的运算符有一个void 返回类型。 (此外,它们都应该将参数作为 const 引用。)
  • 不相关,但是将矩阵包含在单个元素中的意义何在?也许是为了 MRE。
  • @NokiYola 你能接受我下面的回答吗?谢谢。你在cmets里感谢了我,现在你的cmets没了,你删了吗?
  • @DavidBien 我接受了。抱歉,我不知道我可以(也不必)接受答案。不,我没有删除我的 cmets,我想知道它们是如何消失的。

标签: c++ templates


【解决方案1】:

你遇到了一些问题。我认为这些变化是不言自明的。如果没有,请告诉我。 神螺栓:https://godbolt.org/z/ErMdbfEnc

#include <typeinfo>
#include <type_traits>
#include <iostream>

template<typename T1>
class Matrice
{
private:
    T1 table;

public:
    const T1 & getTable() const
    {
        return table;
    }
    T1 & getTable()
    {
        return table;
    }
    Matrice(T1 m_table);

    template<typename T2>
    Matrice<T1>& operator *= ( const Matrice<T2>& );
};

template<typename T1, typename T2, typename T3>
Matrice<T3> operator*(Matrice<T2>&, Matrice<T1>&);

// template<typename T1>
// template<typename T2>
// Matrice<T1>& Matrice<T1>::operator *= (const Matrice<T2>& B);

template<typename T1>
Matrice<T1>::Matrice(T1 m_table):table(m_table)
{
}

template<typename T1, typename T2>
Matrice<typename std::common_type<T1,T2>::type> operator * (Matrice<T2>& M2, Matrice<T1>& M1)
{   
    
    typename std::common_type<T1,T2>::type tab3= (M1.getTable())*(M2.getTable());
    return Matrice<typename std::common_type<T1,T2>::type>(tab3);
}

template<typename T1>
template<typename T2>
Matrice<T1>& Matrice<T1>::operator *= (const Matrice<T2>& B)
{
    table = (T1) table*(B.getTable());
    return *this;
}

int main()
{
    float tab1(12.5);
    int tab2(11);
    Matrice<float> M1(tab1);
    Matrice<int> M2(tab2);
    Matrice<float> M3 =  M1*M2;
    std::cout << M3.getTable() << std::endl;
    M3*=M2;
    return 0;
}

【讨论】:

  • 我在之前的评论中感谢你,但我还问你是否知道 typename std::common_type&lt;T1,T2&gt;::type 是否会在 for 循环的每次迭代中被评估。我还要求您带来的修改精确(特别是const T1 &amp; getTable() const 的第一个const 以及template&lt;typename T1&gt; template&lt;typename T2&gt;template&lt;typename T1, typename T2&gt; 之间的区别)
猜你喜欢
  • 2011-04-10
  • 2021-02-28
  • 1970-01-01
  • 1970-01-01
  • 2012-11-26
  • 1970-01-01
  • 2016-11-06
  • 1970-01-01
相关资源
最近更新 更多