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.
Typically a generic function is an instance of a class that inherits both from function and standard-object. Thus generic functions are both functions (that can be called with and applied to arguments) and ordinary objects.
The ReturnType in TypeScript is a utility type which is quite similar to the Parameters Type. It let's you take the return output of a function, and construct a type based off it.
Generics is the idea to allow type (Integer, String, … etc and user-defined types) to be a parameter to methods, classes and interfaces. For example, classes like an array, map, etc, which can be used using generics very efficiently. We can use them for any type.
The generic argument list is a comma-separated list of type arguments. A type argument is the name of an actual concrete type that replaces a corresponding type parameter in the generic parameter clause of a generic type. The result is a specialized version of that generic type.
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);
// }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With