我正在开发一种基于表达式模板和运算符/函数重载的自动差异化工具。例如,模板 std :: max 函数已成功重载:
namespace ead {
...
template<class A>
struct ExprWrap
{
inline
operator A const& () const
{ return *static_cast<A const*>(this);}
};
class adnumber : public ExprWrap<adnumber>
{ ..... };
template<typename L, typename R>
class MaxExpr : public ExprWrap<MaxExpr<L,R> >{ ...... };
// overloading std::max
template<typename L, typename R>
MaxExpr<L,R>
max (ExprWrap<L> const& l, ExprWrap<R> const& r)
{
return MaxExpr<L,R>(l,r); // return an expression
}
...
}
但是在以下代码中
using namespace std;
using namespace ead;
adnumber x,y,z;
z = max(x,y); // call std::max
如果省略名称空间,则使用std :: ;对于某些其他函数,使用 ead :: 。是否有强制编译器始终选择ead :: namespace的技巧,例如,对于max函数? (请不要使用C ++ 11的特性)为什么编译器认为std :: max是更好的匹配? 好的,我知道在函数名称之前编写 ead :: 并不是什么大问题,但是我想保存用户不要输入。
答案 0 :(得分:2)
考虑std::max
的实例化产生:
std::max(ead::adnumber, ead::number);
这是比max
的签名更好的匹配(完全匹配)。因此它将被调用。您唯一的出路是限定通话,因为您无法通过SFINAE进行std::max
实例化失败,也无法使ead::max
完全通用ead::max(T, T)
。第二次尝试会使调用变得模棱两可。
答案 1 :(得分:0)
假设adnumber
是在命名空间typedef
中定义的用户定义类型(即不 a ead
),则函数max()
应该是已搜索的名称空间ead
和std
。当然,std::max()
是一个完美的匹配,即它会赢得重载决策,除非adnumber
恰好是某些类型typedef
的{{1}} ExprWrap<T>
。这是一个简单的示例,显示了不同的情况:
T
这应该打印
#include <iostream>
namespace ead
{
template <typename T> struct ExprWrap {};
template <typename T>
void max(ExprWrap<T> const&) { std::cout << "ead::max()\n"; }
typedef int builtin;
struct other {};
typedef ExprWrap<int> instance;
struct derived: ExprWrap<int> {};
}
namespace foo
{
template <typename T>
void max(T const&) { std::cout << "foo::max()\n"; }
}
int main()
{
using namespace foo;
using namespace ead;
ead::builtin b;
ead::other o;
ead::instance i;
ead::derived d;
max(b);
max(o);
max(i);
max(d);
}