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_type
std::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