c++ - For type modification traits, should I provide a template-typedef (aka using) convenience wrapper for typename::transform<...>::type? -
i wondering availability of template-typedefs should provide convenience wrappers classes transform types. consider (useless) example:
template< t > struct whatever { typedef typename std::conditional< sizeof(t) <= sizeof(void*), int, long >::type type; };
here, std::conditional
transform
title, used typename transform<...>::type
. also, whatever
transform
, used in same way.
with availability of template-typedefs (aka using
), change interface to:
template< t > using whatever = typename std::conditional< sizeof(t) <= sizeof(void*), int, long >::type;
which simplifies usage. done cases, due required (partial) specialization, end implementation class , wrapper. in case of std::conditional
, you'd end moving std::impl::conditional<...>
, provide wrapper as
namespace std { namespace impl { // "classic" implementation of std::conditional } template< bool b, typename t, typename f > using conditional = typename impl::conditional< b, t, f >::type; }
this leaves question interface/api should provide. see 1 strong point providing wrapper: prevents user errors. see example this question & answer.
for keeping existing interface, see following points:
- consistency. that's type traits , using
- separation of transformer , result of transformation. can pass transformer type, in case of
whatever
above, wouldn't possible anymore. - less code preventing
impl
solution required specializations.
i'd hear arguments or against providing "new" interface, not merely opinions "i second approach better". i'm interested in finding out cases 1 or other approach required or when fails work/scale.
to honest, question lack of experience template-typedefs, if have real-world experience, please shared , bad side of , whether or not should consider typename transform<...>::type
api obsolete c++11 or not.
i following:
- inside namespace (impl, detail, etc.) have classes real work.
- outside, have template aliases clean calling code.
for example, if re-write std::remove_reference, following:
namespace detail { template <typename t> struct remove_reference { using type = t; }; template <typename t> struct remove_reference<t&> { using type = t; }; template <typename t> struct remove_reference<t&&> { using type = t; }; } template <typename t> using remove_reference = typename detail::remove_reference<t>::type;
i didn't compile above code, don't shoot me if made typo.
a benefit calling site more clear. 1 potential drawback if writing higher order generic code , rely on existence of ::type inside of type function, e.g.
template <template <typename...> class f, typename... ts> using apply = typename f<ts...>::type;
though can away changing using line to
using apply = f<ts...>;
without harm. comes down rest of code doing. if type functions need have interface (::type or ::value) need conform them.
Comments
Post a Comment