【问题标题】:no matching function when return different template type from the original返回与原始模板类型不同时没有匹配的功能
【发布时间】:2012-11-22 04:30:56
【问题描述】:

我写了一个简单的模板矩阵类,getMat函数应该返回一个原始大小不同的子矩阵,所以我这样编码:

template <typename T, size_t m, size_t n, typename _Prd>
template<size_t _m, size_t _n> 
Matrix<T,_m,_n,_Prd> Matrix<T,m,n,_Prd>::getMat(const size_t& ulrow, const size_t& ulcol ) const 
{
    assert(_m+ulcol <= m && _n+ulrow <= n) ;
    T temp[_m*_n] ;
    for (size_t j = 0 ; j < _m ; ++j)
        for (size_t i = 0 ; i < _n ; ++i)
            temp[j*_n+i] = data[(ulrow + j) * n + ulcol+i] ;
    return Matrix<T,_m,_n,_Prd>(temp) ;
}

那我这样称呼它:

Matrix<double, 4,4> testmat2(100.0) ;
Matrix<double,2,2> testmat4 =  testmat2.getMat(0,0) ;

它显示如下错误:

main.cpp:127: error: no matching function for call to ‘Matrix<double, 4ul, 4ul, std::equal_to<double> >::getMat(size_t, size_t)’

所以我的问题是为什么编译器没有检测到这个 getMat 函数?

更新:

我以这种方式尝试了代码,它可以工作:

template <typename T, size_t m, size_t n, typename _Prd>
template<size_t _m, size_t _n> 
void Matrix<T,m,n,_Prd>::getMat(Matrix<T,_m,_n,_Prd>& result, const size_t& ulrow, const size_t& ulcol) const
{
    assert(_m+ulcol <= m && _n+ulrow <= n) ;

    for (size_t j = 0 ; j < _m ; ++j)
        for (size_t i = 0 ; i < _n ; ++i)
            result[j*_n+i] = data[(ulrow + j) * n + ulcol+i] ;

}

这是传递要修改的子矩阵作为参考。

所以我的问题是,当这个函数返回不同的模板类型(相同的对象)时,编译器根本没有检测到这个函数。

但我之前在许多转换运算符上使用过这种技术,它们都有效。 例如,这个有效:

template<typename T, int cn, typename _Prd>
template<typename U, typename _Prd2>
Vec<T,cn,_Prd>::operator Vec<U,cn,_Prd2>() const 
{
  U temp[cn] ;
  for (int i = 0 ; i < cn ; ++i)
    temp[i] = static_cast<U>(this->data[i]) ;
  Vec<U,cn,_Prd2> v(temp) ;
  return v ;
};

更新2:

我根据iammilind修改了代码:

template<size_t _m, size_t _n> 
Matrix<T,_m,_n,_Prd> getMat<_m,_n>(const size_t& ulrow, const size_t& ulcol) const ;
// the declaration in the class.

template <typename T, size_t m, size_t n, typename _Prd>
template<size_t _m, size_t _n> 
Matrix<T,_m,_n,_Prd> Matrix<T,m,n,_Prd>::getMat<_m,_n>(const size_t& ulrow, const size_t& ulcol ) const 
{
    assert(_m+ulcol <= m && _n+ulrow <= n) ;
    T temp[_m*_n] ;
    for (size_t j = 0 ; j < _m ; ++j)
        for (size_t i = 0 ; i < _n ; ++i)
            temp[j*_n+i] = data[(ulrow + j) * n + ulcol+i] ;
    return Matrix<T,_m,_n,_Prd>(temp) ;
}

我称之为:

Matrix<double,2,2> testmat7 = testmat2.getMat<2,2>(0,0) ;

但它不能编译:

In file included from main.cpp:13:
Matrix.hpp:125: error: expected initializer before ‘<’ token
In file included from main.cpp:13:
Matrix.hpp:268: error: expected initializer before ‘<’ token
main.cpp: In function ‘int main(int, char**)’:
main.cpp:135: error: ‘class Matrix<double, 4ul, 4ul, std::equal_to<double> >’ has no member named ‘getMat’
main.cpp:135: error: expected unqualified-id before numeric constant

谢谢。

【问题讨论】:

  • getMat() 也是一个 template 函数,因此您必须将其称为 testmat2.getMat&lt;_m,_n&gt;(0,0) 其中 _m,_n 是您的选择。但是您的代码非常混乱。
  • @iammilind,我认为你是对的。我能问一下为什么会让人困惑吗?
  • @iammilind,我觉得不是模板函数的问题,我按照你的建议修改了,但是编译不出来,能否请你提供更多信息?
  • @tomriddle_1234,您可以在代码中粘贴您如何调用getMat&lt;&gt; 的问题。它仍然显示旧方式。
  • @iammilind,它就在那里。非常感谢

标签: c++ templates generics


【解决方案1】:

当你有这个声明时

template <typename T, size_t m, size_t n, typename _Prd>
template<size_t _m, size_t _n> 
Matrix<T,_m,_n,_Prd> Matrix<T,m,n,_Prd>::getMat(const size_t& ulrow, const size_t& ulcol ) const

编译器需要推导出 6 个模板参数。其中四个(即Tmn_Prd)可以从您调用函数的对象中推导出来。其他两个,即_m_n) 无法推断。不过,您可以明确指定它们:

Matrix<double, 4,4> testmat2(100.0);
Matrix<double,2,2> testmat4 = testmat2.getMat<2, 2>(0,0);

如果 testmat2 最终成为从属名称,则需要添加一个额外的 template 关键字:

template <int Size>
void f() {
    Matrix<double, 4, Size> testmat2(100.0);
    Matrix<double, 2, 2>    testmat4 = testmat2.template getMat<2, 2>(0,0);
}

编译器不会使用分配结果的类型来推断模板参数(有时会使用该类型,但前提是存在准备好的重载集并且需要选择函数指针或成员的地址我认为这些中的函数指针)。

转换运算符可以推导出额外的参数,因为它实际上并没有返回类型,而是获取另一个参数,它可以从中潜在地推导出模板参数。您以后更新时遇到的错误可能是由于您声明函数的方式:

template<size_t _m, size_t _n> 
Matrix<T,_m,_n,_Prd> getMat<_m,_n>(const size_t& ulrow, const size_t& ulcol) const ;

getMat() 之后的&lt;_m, _n&gt; 不要去那里。

【讨论】:

  • 非常感谢这个更清晰的答案,但是,我仍然不知道如何在不使用荒谬的额外模板语法的情况下为我的模板类编写一个合理的 getMat 函数?编码 getMat 的正确方法是什么,允许像这样使用 Matrix testmat4 = testmat2.getMat(0,0) ; ?我应该在课堂外制作这个功能吗?或者我应该编写一个子矩阵构造函数而不是 getMat 函数?
  • 我只想将其设为构造函数:Matrix&lt;double, 2, 2&gt; testmat4(testmat2); 和类似的赋值方法(但是,T a = v; 符号不是赋值,即不支持此方法)。无法从getMat() 的返回类型中推断出该对象旁边发生了什么。您可能会创建某种句柄来保留指向原始指针的指针,并且只有一个转换运算符,但我有构造函数和赋值。
猜你喜欢
  • 1970-01-01
  • 2013-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-29
相关资源
最近更新 更多