0

我正在开发一个基于表达式模板和运算符/函数重载的自动微分工具。例如,模板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:: 命名空间的技巧,例如用于 max 函数?(请不要使用 C++11 功能)为什么编译器认为 std::max 更匹配?
好的,我知道在函数名称之前写ead::没什么大不了的,但我想避免用户打字。

4

2 回答 2

2

考虑std::max产量的实例化:

std::max(ead::adnumber, ead::number);

这是比您的签名更好的匹配max(它是完全匹配)。因此它将被调用。你唯一的出路是限定调用,因为你std::max不能通过 SFINAE 实例化失败或使你ead::max的完全通用ead::max(T, T)。第二次尝试会使调用变得模棱两可。

于 2012-11-27T23:56:53.887 回答
0

假设在 namespace 中定义adnumber了一个用户定义类型(即不是a typedefead,则该函数max()应该在 namespaceseadstd. 当然,std::max()这是一个完美的匹配,即它赢得了重载决议,除非adnumber碰巧是某种类型的typedeffor 。这是一个简化的示例,显示了不同的情况: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);
}

这应该打印

foo::max()
foo::max()
ead::max()
foo::max()
于 2012-11-27T23:56:32.373 回答