【发布时间】:2012-06-18 15:21:53
【问题描述】:
我正在开发一个使用多种算术类型的项目。所以我做了一个标题,其中定义了用户定义的算术类型的最低要求:
user_defined_arithmetic.h:
typedef double ArithmeticF; // The user chooses what type he
// wants to use to represent a real number
namespace arithmetic // and defines the functions related to that type
{
const ArithmeticF sin(const ArithmeticF& x);
const ArithmeticF cos(const ArithmeticF& x);
const ArithmeticF tan(const ArithmeticF& x);
...
}
困扰我的是,当我使用这样的代码时:
#include "user_defined_arithmetic.h"
void some_function()
{
using namespace arithmetic;
ArithmeticF lala(3);
sin(lala);
}
我得到一个编译器错误:
error: call of overloaded 'sin(ArithmeticF&)' is ambiguous
candidates are:
double sin(double)
const ArithmeticF arithmetic::sin(const ArithmeticF&)
我从未使用过<math.h> 标头,只使用了<cmath>。我从未在头文件中使用过using namespace std。
我正在使用 gcc 4.6.*。我检查了包含模棱两可声明的标题是什么,结果是:
mathcalls.h:
Prototype declarations for math functions; helper file for <math.h>.
...
我知道,<cmath> 包括 <math.h>,但它应该屏蔽 std 命名空间的声明。我深入研究<cmath> 标头并找到:
cmath.h:
...
#include <math.h>
...
// Get rid of those macros defined in <math.h> in lieu of real functions.
#undef abs
#undef div
#undef acos
...
namespace std _GLIBCXX_VISIBILITY(default)
{
...
所以命名空间std 在#include <math.h> 之后开始。这里有什么问题,还是我误会了什么?
【问题讨论】:
-
您可能需要重新考虑一些事情:当使用算术类型(整数类型 + 双精度 + 浮点数)时,按值传递通常比按引用传递更有效(也更常见)。调用您想要特定版本的函数时,请限定调用,而不是添加
using namespace X。或者,您可以使用 using 指令 (using arithmetic::sin)。最后,通过编辑typedef来更改类型的整个方法是一个非常糟糕的主意。 -
@DavidRodriguez-dribeas:谢谢!拜托,你能提示我一个替代解决方案吗?我使用的是通过引用传递,因为数字可以是自定义类型。这意味着它甚至可以达到几千字节。我希望当我内联函数并在内联中使用 std 基本函数时,不会造成任何伤害。还是会?请给我一些建议好吗?
-
@DavidRodriguez-dribeas:我知道 C++ 方法是声明一个抽象类,但是当您使用内置类型时,我用于矩阵计算的库会使用显着的优化。我只是不想失去这个优势
-
你的实现可以是一个只使用特性的模板(不管是不是一个类是一个不同的问题,如果你问我免费函数很好)。您的算法 将适用于任何算术 类型,并且用户代码可以决定本地 使用哪种类型,而无需修改
typedef。也就是说,用户可以知道他们正在使用的类型,而无需在标题中搜索typedef。此外,您将能够在单个应用程序中使用多种类型。 -
另请参阅 Red Hat 博客中 Jonathan Wakely 的 Why < cstdlib > is more complicated than you might think。 Wakely 是维护 GNU 的 C++ 标准库的 GCC 开发人员之一。他专门讨论了数学函数及其可能引起的麻烦。简而言之,C++ 有重载,所以有三个
abs、三个log等。重载是int、double和long double以满足您的需要。但是 C 只有一个函数。
标签: c++ namespaces cmath