c++ - Why is `std::common_type_t<std::ostream &, std::ostream &>` equal to `std::ostream` and not `std::ostream &`? -
i'm working on small library, , 1 of things need apply visitors data , return results.
in older c++ code, visitors expected declare typedef return_type. instance, boost::static_visitor that.
in newer code, visitors deprecated. in c++14 can use decltype(auto), i'm trying using std::common_type can in c++11.
i tried backporting example implementation of std::common_type c++11 , using figure out return types.
however unexpected results when using "possible implementation" on cppreference.com
#include <ostream> #include <type_traits> // decay_t backport template <typename t> using decay_t = typename std::decay<t>::type; // common_type backport template <typename t, typename... ts> struct common_type; template <typename t> struct common_type<t> { using type = decay_t<t>; }; template <typename t1, typename t2> struct common_type<t1, t2> { using type = decay_t<decltype(true ? std::declval<t1>() : std::declval<t2>())>; }; // todo: needed? /* template <typename t> struct common_type<t, t> { using type = t; }; */ template <typename t1, typename t2, typename t3, typename... ts> struct common_type<t1, t2, t3, ts...> { using type = typename common_type<typename common_type<t1, t2>::type, t3, ts...>::type; }; template <typename t, typename... ts> using common_type_t = typename common_type<t, ts...>::type; // static_assert(std::is_same<common_type_t<std::ostream &, std::ostream &>, std::ostream &>::value, "this expected!"); static_assert(std::is_same<common_type_t<std::ostream &, std::ostream &>, std::ostream>::value, "hmm..."); int main() {} what "should" result of std::common_type_t<std::ostream&, std::ostream&> be? should not std::ostream &? if not, why both gcc 5.4.0 , clang 3.8.0 think std::ostream?
note: when use "real" std::common_type_t in c++14, still std::ostream , not std::ostream &.
is specializing std::common_type std::common_type_t<t, t> t valid approach? seems work in program, feels hack.
see this question related discussion on history around common_type , why doesn't yield reference.
is specializing
std::common_typestd::common_type_t<t, t>t valid approach?
i assume mean specializing your implementation of common_type (since can't specialize other one). , no, isn't sufficient. want common_type<base&, derived&> base&, instantiation won't go through specialization.
what want not use decay. reason decay in there drop surprise rvalue reference declval provides in cases. want maintain lvalue reference - add own type trait:
template <class t> using common_decay_t = std::conditional_t< std::is_lvalue_reference<t>::value, t, std::remove_reference_t<t>>; and use instead of normal decay.
Comments
Post a Comment