简体   繁体   English

定义模板运算符重载时出错

[英]Error defining a templated operator overload

Here's an attempted templated overload of operator+. 这是一个尝试的operator +模板重载。 This fails to compile with both gcc 4.8 and icc 14.0.3. 无法同时使用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;
}

However, the commented overload works fine. 但是,注释的重载可以正常工作。 What is the difference? 有什么区别? Why doesn't the template with two parameters match? 为什么带有两个参数的模板不匹配?

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;

The compiler is telling you why it failed: 编译器告诉您失败的原因:

temp2.cpp:25:6: note: template argument deduction/substitution failed: temp2.​​cpp:25:6:注意:模板参数推导/替换失败:
temp2.cpp:33:19: note: couldn't deduce template parameter 'U' temp2.​​cpp:33:19:注意:无法推断出模板参数“ U”

The template parameter U only appears in the return type of the function template, and so it cannot be deduced. 模板参数U仅出现在功能模板的返回类型中,因此无法推导。 Your code will compile if you explicitly list the template arguments 如果您明确列出模板参数,则将编译您的代码

B<double> c = operator+<double, double>(a, b);

And if you swap the order of the template parameters so that U appears before T , you can still allow T to be deduced. 而且,如果交换模板参数的顺序,以使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);

The commented out operator+ implementation works because the return type is also using the same type argument T , thus allowing it to be deduced from the function template arguments. 注释掉的operator+实现之所以起作用,是因为返回类型也使用相同的类型参数T ,从而允许从函数模板参数中推导出它。

In

B<double> c = a+b;

the type template parameter U in 类型模板参数U in

B<U> operator+(A<T> const& t, A<T> const& u)

cannot be deduced. 无法推论。 U will not be deduced as double simply because the result of the call is being assigned to B<double> . 仅将调用结果分配给B<double>不会将U推导出为double You would have to explicitly specify U as double , for example by the following, 您必须将U明确指定为double ,例如,通过以下方式,

B<double> c = operator+<double, double>(a, b);

Now obviously this is likely not a desirable situation. 现在显然这可能不是理想的情况。 So what can you do? 所以,你可以做什么? Well, it's hard to say because you haven't specified what A and B are to be used for. 好吧,很难说,因为您尚未指定AB的用途。 But, as you've already discovered, your code compiles with the commented-out operator, 但是,正如您已经发现的那样,您的代码是使用注释掉的运算符编译的,

template<typename T>
B<T> operator+(A<T> const& t, A<T> const& u)
{
    return (B<T>)t + (B<T>)u;
}

For some reason you seem to want it to be possible to use the result to initialize a B<U> where U might not be the same as T , so perhaps the right solution is to make it possible to construct B<U> from B<T> : 由于某种原因,您似乎希望可以使用结果初始化B<U> ,其中U可能与T ,所以也许正确的解决方案是使从B<T>构造B<U> B<T>

template <typename T>
class B
{
public:
  template <typename U>
  B(const B<U>& rhs) {
    // ...
  }
  // ...
};

(You likely also want to write a similar assignment operator.) (您可能还想编写类似的赋值运算符。)

The error message from the compiler is clear. 来自编译器的错误消息是明确的。 It is not able to deduce parameter U to instantiate the operator+ function. 无法推导出参数U来实例化operator+功能。

You can be explicit by using: 您可以使用以下方法明确显示:

B<double> c = operator+<double, double>(a,b);

Return types are not deduced. 不推论返回类型。

You can fake it with expression templates. 您可以使用表达式模板来伪造它。

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};
}

which should give you the idea. 这应该给你的想法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM