Question

I'm developing an automatic differentiation tool based on expression templates and operator/function overloading. The template std::max function, for example, was successfully overloaded:

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
    }
    ...
}

but in a code like the following

using namespace std;
using namespace ead;

adnumber x,y,z;
z = max(x,y);      // call std::max

std:: is used if the namespace is omitted, and for some other functions, ead:: is used. Is there a trick to force the compiler to always choose the ead:: namespace, for example, for max function? (without C++11 features, please) Why compiler thinks the std::max is a better match?
Ok, I know that to write ead:: before functions name is not a big deal, but I'd like to save the user from typing.

Was it helpful?

Solution

Consider what instantiation of std::max yields:

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

This is a better match than your signature of max (it is an exact match). Thus it will be called. Your only way out is to qualify the call, because you cannot make instantiation of std::max fail through SFINAE or make your ead::max a fully generic ead::max(T, T) as well. The second attempt would make the call ambiguous.

OTHER TIPS

Assuming adnumber is a user defined type (i.e., not a typedef) defined in namespace ead, the function max() should be searched namespaces ead and std. Of course, std::max() is a perfect match, i.e., it wins overload resolution unless adnumber happens to be a typedef for ExprWrap<T> for some type T. Here is a boiled down example showing the different cases:

#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);
}

This should print

foo::max()
foo::max()
ead::max()
foo::max()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top