如果类型T和U相同,则函数模板不能推导出类型

时间:2013-07-26 18:47:58

标签: c++ templates template-deduction

这个问题源自我昨天收到的answer。对于以下函数,如果couldn't deduce template parameter ‘V’T都为U,则会收到错误std::complex<double>。如果TU不同,则函数会按预期编译并运行。

template<class T, class U, class V>
auto operator*(const T a, const matrix<U> A) -> decltype(std::declval<T>()*std::declval<U>())
{
    matrix<V> B(A.size(1),A.size(2));
    for(int ii = 0; ii < B.size(1); ii++)
    {
        for(int jj = 0; jj < B.size(2); jj++)
        {
            B(ii,jj) = a*A(ii,jj);
        }
    }
    return B;
}

用法如下:

std::complex<double> a1;
matrix<std::complex<double> > A1;
double a2;
matrix<std::complex<double> > A2;

/* ... */

matrix<std::complex<double> > B1 = a1*A1; // Compiler error
matrix<std::complex<double> > B2 = a2*A2; // Compiles and runs fine.

我还应该提一下,我正在使用g ++ 4.7.3和C ++ 11进行编译。

修改

我找到的解决方法是提供此功能模板:

template<class T>
matrix<T> operator*(const T a, const matrix<T> A)
{
    matrix<T> B(A.size(1),A.size(2));
    for(int ii = 0; ii < B.size(1); ii++)
    {
        for(int jj = 0; jj < B.size(2); jj++)
        {
            B(ii,jj) = a*A(ii,jj);
        }
    }
    return B;
}

通过这个添加,以上两种情况都可以正确编译和运行。

3 个答案:

答案 0 :(得分:3)

我认为必须涉及operator*的另一个重载,因为V 无法根据声明推断

template<class T, class U, class V>
auto operator*(const T a, const matrix<U> A)
  -> decltype(std::declval<T>()*std::declval<U>());

调用此函数的唯一方法是明确指定V,例如operator*<int, long, long>(...)


编辑:在第二个代码示例中查看operator*(T, matrix<T>)的签名,看起来您的第一个代码示例应该是:

template<class T, class U>
auto operator*(const T a, const matrix<U>& A) -> matrix<decltype(a*A(0,0))>
{
    matrix<decltype(a*A(0,0))> B(A.size(1),A.size(2));
    for(int ii = 0; ii < B.size(1); ii++)
    {
        for(int jj = 0; jj < B.size(2); jj++)
        {
            B(ii,jj) = a*A(ii,jj);
        }
    }
    return B;
}

operator*(T,matrix<T>)不一定是特殊情况。

答案 1 :(得分:2)

我认为如果T和U不同,则会调用另一个函数,因为编译器是正确的,V不能推断,周期。即使我不能推断你认为该参数应该是什么。 Here's proof that the second doesn't compile and run either,这意味着在这种情况下调用了不同的函数。显而易见的解决方案是简单地删除class V模板参数类型,并简单地使用推导的类型。也许你想要一些more like this?

再次查看您的代码,您说的代码失败的是complex * matrix,而第二个代码是matrix*matrix。还有哪些operator*被定义了?

<小时/> 不相关的接受参数的三种常用方法是Tconst T&T&&。没有理由拥有const T参数类型。我相信你错过了&

答案 2 :(得分:2)

问题不在于TU是相同的,但在提及V类型的函数原型中有注意到。

考虑到你使用V来声明你返回的B,并且你将返回类型定义为T()* U(),我想知道matrix<V>应该是什么。

我希望B和返回类型为matrix<decltype(declval<T>()*declval<U>())>,没有V(不应该在参数列表中)