Перегрузка функций C++, шаблоны выражений и пространство имен

Я разрабатываю инструмент автоматического дифференцирования на основе шаблонов выражений и перегрузки операторов / функций. Например, функция 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:: before имя функции не имеет большого значения, но я бы хотел уберечь пользователя от набора текста.

2 ответа

Решение

Рассмотрим, что такое экземпляр std::max выходы:

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

Это лучше, чем ваша подпись max (это точное совпадение). Таким образом это будет называться. Ваш единственный выход - квалифицировать вызов, потому что вы не можете создать экземпляр std::max провалиться через SFINAE или сделать свой ead::max полностью универсальный ead::max(T, T) также. Вторая попытка сделает вызов неоднозначным.

Если предположить, adnumber это пользовательский тип (т.е. не typedef) определен в пространстве имен ead, функция max() следует искать пространства имен ead а также std, Конечно, std::max() идеально подходит, т. е. выигрывает разрешение перегрузки adnumber случается быть typedef за 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()
Другие вопросы по тегам