使我的结构或类与std :: round兼容

时间:2016-04-12 12:54:50

标签: c++ math rounding

鉴于以下内容,如何使我的类或结构与 std :: round 兼容? (我假设同样的事情也可以用于 std :: floor std :: ceil )。我可以这样做吗?

C++ Shell version

#include <cmath>

struct Rectangle
{
    Rectangle(double _x1, double _x2, double _y1, double _y2) : 

        x1(_x1), y1(_y1), x2(_x2), y2(_y2) 

    {

    }

    double x1, y1, x2, y2;
};

int main(void )
{
    auto r = Rectangle(10.3, 10.4, 10.5, 10.6);

    r = std::round(r);

    std::cout << r.x1 << "," << r.y1 << "," << r.x2 << "," << r.y2 << std::endl;
}

3 个答案:

答案 0 :(得分:5)

您无法std::round执行此操作:它已经定义,并且您无法在命名空间std中添加新的重载。

可以做的是编写一个新函数并使用它(或者像Tartan Llama所示的简单函数或方法,但我在这里更喜欢自由函数)

Rectangle round(Rectangle const &original) {
    return { std::round(original.x1), std::round(original.y1),
             std::round(original.x2), std::round(original.y2) };
}

同样,将此添加到命名空间std是非法的。只需确保它与Rectangle本身位于同一名称空间,ADL就会为您找到它。

顺便说一下 - 让你的构造函数参数和它们对应的成员对应的命令不同,这里容易引起混淆和容易出错。在统一初始化和上面的显式构造函数之间切换需要更改参数顺序,但编译器无法发现它。

答案 1 :(得分:3)

如果你想要一个函数来舍入Rectangle的所有点并返回一个新点,那么自己写一下;尝试使用std::round来实现这一点并不合理。

一个选项:

struct Rectangle
{
    Rectangle(double _x1, double _x2, double _y1, double _y2) : 
      x1(_x1), y1(_y1), x2(_x2), y2(_y2) 
    { }

    Rectangle round() {
        return { std::round(x1), std::round(x2), 
                 std::round(y1), std::round(y2) };   
    }

    double x1, y1, x2, y2;
};

然后就这样称呼它:

r = r.round();

答案 2 :(得分:1)

讨论和思考:

我最初的想法是提供@Useless的答案: - 与参数在同一名称空间中的自由函数是正确的方法。

然而,更仔细地考虑函数round的推断语义,为我提出了一个问题:

round听起来更像是命令而不是修饰符。我知道已经有一个std :: round返回一个整数参数的副本,但是还有一个std::sort可以对一个对象进行排序。

在我看来,如果你想要一个圆形副本,你可能想要调用一个名为rounded的函数,如果你想让一个对象自己进行舍入,你可能想要调用round在它上面。

如果您同意这种想法,代码将开始如下所示:

#include <cmath>
#include <iostream>

struct Rectangle
{
    Rectangle(double _x1, double _x2, double _y1, double _y2) 
    : x1(_x1), y1(_y1), x2(_x2), y2(_y2) 
    {
    }

    Rectangle& round() {
      using std::round;
      x1 = round(x1);
      y1 = round(y1);
      x2 = round(x2);
      y2 = round(y2);
      return *this;
    }

  Rectangle& normalise()
  {
    // something here
    return *this;
  }

    double x1, y1, x2, y2;
};

Rectangle rounded(Rectangle r)
{
  return r.round();
}

Rectangle& round(Rectangle& r)
{
  return r.round();
}

Rectangle normalised(Rectangle r)
{
  return r.normalise();
}

Rectangle& normalise(Rectangle& r)
{
  return r.normalise();
}

int main(void )
{
    auto r = Rectangle(10.3, 10.4, 10.5, 10.6);

  // take a rounded, normalised copy
  auto r1 = rounded(normalised(r));
  // take a rounded copy
  auto r2 = rounded(r);

  // take a copy
  auto r3 = r;

  // normalise and round the copy
  normalise(round(r3));

  round(r);

  std::cout << r.x1 << "," << r.y1 << "," << r.x2 << "," << r.y2 << std::endl;
}