Я разрабатываю инструмент автоматического дифференцирования на основе шаблонов выражений и перегрузки операторов / функций. Шаблон станд :: макс функция, например, была успешно перегружена:
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
станд :: используется, если пространство имен опущено, а для некоторых других функций Свинец :: используется. Есть ли хитрость, заставляющая компилятор всегда выбирать пространство имен ead ::, например, для функции max? (без функций C ++ 11, пожалуйста) Почему компилятор считает, что std :: max лучше подходит?
Ок я знаю что написать Свинец :: до имени функции не имеет большого значения, но я бы хотел уберечь пользователя от набора текста.
Рассмотрим, что такое экземпляр 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()