这是运算符+的模拟重载尝试。这无法使用gcc 4.8和icc 14.0.3进行编译。
template <typename T>
class B
{
public:
B operator+(const B& rhs)
{
return *this;
}
};
template <typename T>
class A
{
public:
operator B<T>() const{return B<T>();}
};
// template<typename T>
// B<T> operator+(A<T> const& t, A<T> const& u)
// {
// return (B<T>)t + (B<T>)u;
// }
template<typename T, typename U>
B<U> operator+(A<T> const& t, A<T> const& u)
{
return (B<U>)t + (B<U>)u;
}
int main()
{
A<double> a,b;
B<double> c = a+b;
return 0;
}
然而,评论的重载工作正常。有什么不同?为什么带有两个参数的模板不匹配?
g++48 -std=c++11 temp2.cpp
temp2.cpp: In function ‘int main()’:
temp2.cpp:33:18: error: no match for ‘operator+’ (operand types are ‘A<double>’ and ‘A<double>’)
B<double> c = a+b;
^
temp2.cpp:33:18: note: candidate is:
temp2.cpp:25:6: note: template<class T, class U> B<U> operator+(const A<T>&, const A<T>&)
B<U> operator+(A<T> const& t, A<T> const& u)
^
temp2.cpp:25:6: note: template argument deduction/substitution failed:
temp2.cpp:33:19: note: couldn't deduce template parameter ‘U’
B<double> c = a+b;
答案 0 :(得分:6)
编译器告诉你失败的原因:
temp2.cpp:25:6:注意:模板参数扣除/替换失败:
temp2.cpp:33:19:注意:无法推断出模板参数'U'
模板参数U
仅出现在函数模板的返回类型中,因此无法推断出。如果您明确列出模板参数
B<double> c = operator+<double, double>(a, b);
如果你交换模板参数的顺序,以便U
出现在T
之前,你仍然可以推导出T
。
template<typename U, typename T>
B<U> operator+(A<T> const& t, A<T> const& u)
{
return (B<U>)t + (B<U>)u;
}
B<double> c = operator+<double>(a, b);
注释掉的operator+
实现有效,因为返回类型也使用相同的类型参数T
,因此允许从函数模板参数中推导出它。
答案 1 :(得分:5)
在
B<double> c = a+b;
中的类型模板参数
U
B<U> operator+(A<T> const& t, A<T> const& u)
无法推断。 U
不会仅仅因为呼叫结果已分配给double
而被推断为B<double>
。您必须明确指定U
为double
,例如通过以下内容
B<double> c = operator+<double, double>(a, b);
现在显然这可能不是一个理想的情况。所以,你可以做什么?嗯,很难说,因为您还没有指定A
和B
的用途。但是,正如您已经发现的那样,您的代码将使用已注释掉的运算符进行编译,
template<typename T>
B<T> operator+(A<T> const& t, A<T> const& u)
{
return (B<T>)t + (B<T>)u;
}
出于某种原因,您似乎希望可以使用结果来初始化B<U>
,其中U
可能与T
不同,所以也许正确的解决方案是可以从B<U>
构建B<T>
:
template <typename T>
class B
{
public:
template <typename U>
B(const B<U>& rhs) {
// ...
}
// ...
};
(您可能还想编写类似的赋值运算符。)
答案 2 :(得分:2)
编译器的错误消息很明确。它无法推导出参数U
来实例化operator+
函数。
您可以使用以下方式明确:
B<double> c = operator+<double, double>(a,b);
答案 3 :(得分:2)
不推断退货类型。
您可以使用表达式模板伪造它。
template<template<class>class Op, class Rhs, class Lhs>
struct deferred{
Lhs lhs; Rhs rhs;
template<typename Result>
operator Result() const { return Op<Result>{}( std::forward<Lhs>(lhs), std::forward<Rhs>(rhs) ); }
};
template<class R> sum;
template<class U> sum<B<U>>{
template<class Lhs, class Rhs>
B<U> operator()( A<Lhs> const& lhs, A<Rhs> const& rhs )const{
return B<Lhs>(lhs)+B<Rhs>(rhs);
}
};
template<class T>
deferred<sum, A<T>const&, A<T>const&> operator+( A<T>const& a, A<T>const& b){
return {a,b};
}
应该会给你一个想法。