强制C++函数的用户确认数值常量参数的语义含义的最佳方法是什么?

Bry*_*man 12 c++

我想编写函数接口,强制用户承认内置常量的语义.例如,我想采取

void rotate(float angle); // Rotate the world by an angle in radians.
Run Code Online (Sandbox Code Playgroud)

并将其更改为

void rotate(Radians angle);
Run Code Online (Sandbox Code Playgroud)

我是否正确地相信制作Radians类的问题在于它会增加代码并使程序变慢.有一个更好的方法吗?

Omn*_*ous 21

不,有可能将一个Radians类应该被大多数不错的编译器优化成一个不比普通浮点慢的东西.您可能对boost.units感兴趣.

事实上,使用boost.units你甚至可以设置它,这样如果有人想以度数传递一个角度,它会在传递给函数之前自动转换为弧度.这可能会使事情变得缓慢,但它会安排它,以便您可以更改函数所需的单位,而无需返回并编辑大量代码.

而且,当你最终想要编辑所有代码时,你可以暂时修复它,以便转换不起作用,让编译器为你找到它.

能够让编译器为你强制执行这样的约束,没有运行时损失,甚至可能为你编写所有转换代码(运行时间非常小),这是C++真正的优点之一,值得增加复杂性在C.

这是一个非常简单的版本,如果你手工编写它,这个类可能会是什么样子:

#include <cmath>

// This class is tiny enough because it has no virtual functions and only one
// data member that it's likely more efficient to pass by value than by
// reference.
class Radians {
 public:
   // If you don't put in explicit, the compiler will automatically convert a
   // float to a Radians for you and undo all of the hard work you did to make
   // sure callers express their intentions.
   explicit Radians(float radians) : value_(radians) {}

   float getValue() const { return value_; }
   void setValue(float radians)  { value_ = radians; }

   float asDegrees() const { return value_ * 180 / M_PI; }

   // This allows you to say Radians r = Radians::fromDegrees(something);
   static Radians fromDegrees(float degrees) {
      return Radians(degrees * M_PI / 180);
   }

 private:
   float value_;
};
Run Code Online (Sandbox Code Playgroud)

注意如何在类体中声明所有函数.这使得它们都隐含地拥有inline关键字.一个好的编译器将优化所有这些功能.当然,转换函数会生成执行转换的代码,但除此之外它将与裸浮点相同.

  • +1没有忘记评论显式构造函数. (2认同)

Bil*_*ill 6

这个约束的关键是声明你的构造函数:

class Radians
{
public:
  explicit Radians(float value) : m_value(value) {}
private:
  float m_value;
};
Run Code Online (Sandbox Code Playgroud)

那样你的用户就无法输入rotate(4.5).他们必须打字rotate(Radians(4.5)).


ale*_*rus 5

这是完成此任务的完美方式.这就是使C成为C++的原因.使用您需要的类并封装数据.它不会使程序显着变慢,因为编译器会执行所有优化.

  • 我提到了boost.units,因为它会为你做很多工作. (3认同)