c ++函数重载,表达式模板和命名空间

时间:2012-11-27 23:32:41

标签: c++ namespaces overloading expression-templates

我正在开发一种基于表达式模板和运算符/函数重载的自动差异化工具。例如,模板 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 :: 并不是什么大问题,但是我想保存用户不要输入。

2 个答案:

答案 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()应该是已搜索的名称空间eadstd。当然,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);
}