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