Suppose, I want to develop a generic library which should be usable with number-like types including double and user-defined types. The problem, I'm facing right now is that I don't know how to write the return type of a function template much like this one:
template<class T>
auto transmogrify(T x)
-> ???
{
using std::abs;
return abs(x)+2.0;
}
The using declaration makes this function template's body work for primitive types because these don't have an associated namespace (and hence, there is no ADL). But I want transmogrify to use specialized abs functions in case the author of a user-defined type provides his own abs function. I can't simply use
-> decltype( abs(x)+2.0 )
because this would not work for, say, doubles since std::abs is not in scope (as far as I can tell). But writing
-> decltype( std::abs(x)+2.0 )
would disable ADL. But disabling ADL is not an option. Also, the value returned by a specialized abs function might not be of type T but some other type.
Any ideas on how to solve the return type issue while (a) keeping ADL and (b) falling back on some default function (like std::abs in this case) for types that don't provide a specialized abs.
Use a separate namespace, where you can put the using clause. This prevents the namespace pollution, since the using clause only applies to that namespace. I would recommend naming it something unique, so you don't accidentally spread it around.
namespace transmog_detail
{
using std::abs;
template<class T>
auto transmogrify(T x) -> decltype(abs(x) + 2.0)
{
return abs(x) + 2.0;
}
}
// Then pull it into the current namespace, as recommended by @LucDanton.
using transmog_detail::transmogrify;
// Or if there is a reason, you can forward.
// template<class T>
// auto transmogrify(T x)
// -> decltype(transmog_detail::transmogrify(x))
// {
// return transmog_detail::transmogrify(x);
// }