【问题标题】:Infer the (templated) return type of operator+ and other operators推断 operator+ 和其他运算符的(模板化)返回类型
【发布时间】:2020-02-09 14:13:13
【问题描述】:

我正在实现一个二维向量,它可以采用任何算术类型作为其坐标。我想实现一个operator+ 运算符,它从上下文推断其返回类型,就像unsigned x = 2l + 3.1; 知道+ 的结果应该是unsigned,因为它被分配给unsigned

到目前为止,我所拥有的灵感来自Templates inferring type T from return type

#include <array>
#include <type_traits>

template<typename T,
         typename = std::enable_if_t<std::is_arithmetic_v<T>, T>>
class Vec2
{
    std::array<T, 2> _data;

public:
    // Constructors
    Vec2(T x, T y): _data{x, y} {}

    // Operators
    template<typename TB, // second operand's coordinates type
             typename TR> // result's coordinates type
    Vec2<TR> operator+(const Vec2<TB> v) const
    {
        return Vec2<TR>(_data[0] + v._data[0],
                        _data[1] + v._data[1]);
    }
};

int main(void)
{
    Vec2 vi{0, 2};
    Vec2 vf{1.4, 2.2};

    Vec2<int> res = vi + vf;
}

我得到一个错误,说它无法推断出用于返回值的类型:

$ g++ -Wall -Wextra -std=c++17 poc.cc
poc.cc: In function ‘int main()’:
poc.cc:29:24: error: no match for ‘operator+’ (operand types are ‘Vec2<int, int>’ and ‘Vec2<double, double>’)
   29 |     Vec2<int> res = vi + vf;
      |                     ~~ ^ ~~
      |                     |    |
      |                     |    Vec2<double,double>
      |                     Vec2<int,int>
poc.cc:17:14: note: candidate: ‘template<class TB, class TR> Vec2<TR> Vec2<T, <template-parameter-1-2> >::operator+(Vec2<TB>) const [with TB = TB; TR = TR; T = int; <template-parameter-1-2> = int]’
   17 |     Vec2<TR> operator+(const Vec2<TB> v) const
      |              ^~~~~~~~
poc.cc:17:14: note:   template argument deduction/substitution failed:
poc.cc:29:26: note:   couldn’t deduce template parameter ‘TR’
   29 |     Vec2<int> res = vi + vf;
      |                          ^~
poc.cc:29:15: warning: unused variable ‘res’ [-Wunused-variable]
   29 |     Vec2<int> res = vi + vf;
      |               ^~~

【问题讨论】:

  • 2l + 3.1 的结果是double。一个好的编译器应该警告将其分配给unsigned
  • @rustyx,哦,所以它是在 double 上计算的,然后 然后 转换为无符号的?你知道标准中的哪个地方是这么说的吗?

标签: c++ templates operator-overloading return-type


【解决方案1】:

在 C++ 中,+ 运算符重载无法确定其结果将分配给什么。 C++ 根本无法以这种方式工作。

在许多情况下,可以以稍微不同的方式设计一种替代方法。首先让+ 运算符找出最佳返回类型应该是什么:

template<typename TB> // result's coordinates type
auto operator+(const Vec2<TB> v) const
{
    typedef decltype( static_cast<T>(0) + static_cast<TB>(0) ) ret_t;

    return Vec2<ret_t>(_data[0] + v._data[0],
                    _data[1] + v._data[1]);
}

您确保TTB 都是算术类型,因此这是通过decltype 找出它的最简单方法。

因此,将ints 的Vec2 添加到doubles 的Vec2 应该会产生Vec2&lt;double&gt;。但是,如果它被分配给Vec2&lt;int&gt; 怎么办?好吧,您只需要一个转换运算符...

template<typename TB>
operator Vec2<TB>() const
{
    return Vec2<TB>(_data[0], _data[1]);
}

...希望一切顺利。

【讨论】:

  • 非常感谢。所以我想做的事情是不可能的,但这是我的第二个最佳选择,我没有找到一种优雅的方式来实现它,你的很好(如果在某些代码中实际使用需要一个很好的评论,但它很好)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-06
  • 1970-01-01
  • 2015-12-14
  • 2013-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多