Is there a c++ trait to find the most restricted type between two types in C++?












5















I would like a type trait common



so that



common<int,int>::type              -> int
common<const int, int>::type -> const int
common<int, int &>::type -> int
common<int &, int &>::type -> int &
common<int &, int const &>::type -> int const &


that is the result type should be the more restricted of the two. Is there a trait in the C++11 std that can do this or do I have to roll my own?



My use case is that I have a something similar to



template <typename T0, typename T1>
struct Foo {

BOOST_STATIC_ASSERT(
std::is_same
< typename std::decay<T0>::type
, typename std::decay<T1>::type
>::value
);

// I need to find T which is the most restrictive common
// type between T0 and T1
typedef typename common<T0,T1>::type T

T0 t0;
T1 t1;

T choose(bool c){
return c ? t0 : t1;
}

}









share|improve this question





























    5















    I would like a type trait common



    so that



    common<int,int>::type              -> int
    common<const int, int>::type -> const int
    common<int, int &>::type -> int
    common<int &, int &>::type -> int &
    common<int &, int const &>::type -> int const &


    that is the result type should be the more restricted of the two. Is there a trait in the C++11 std that can do this or do I have to roll my own?



    My use case is that I have a something similar to



    template <typename T0, typename T1>
    struct Foo {

    BOOST_STATIC_ASSERT(
    std::is_same
    < typename std::decay<T0>::type
    , typename std::decay<T1>::type
    >::value
    );

    // I need to find T which is the most restrictive common
    // type between T0 and T1
    typedef typename common<T0,T1>::type T

    T0 t0;
    T1 t1;

    T choose(bool c){
    return c ? t0 : t1;
    }

    }









    share|improve this question



























      5












      5








      5


      1






      I would like a type trait common



      so that



      common<int,int>::type              -> int
      common<const int, int>::type -> const int
      common<int, int &>::type -> int
      common<int &, int &>::type -> int &
      common<int &, int const &>::type -> int const &


      that is the result type should be the more restricted of the two. Is there a trait in the C++11 std that can do this or do I have to roll my own?



      My use case is that I have a something similar to



      template <typename T0, typename T1>
      struct Foo {

      BOOST_STATIC_ASSERT(
      std::is_same
      < typename std::decay<T0>::type
      , typename std::decay<T1>::type
      >::value
      );

      // I need to find T which is the most restrictive common
      // type between T0 and T1
      typedef typename common<T0,T1>::type T

      T0 t0;
      T1 t1;

      T choose(bool c){
      return c ? t0 : t1;
      }

      }









      share|improve this question
















      I would like a type trait common



      so that



      common<int,int>::type              -> int
      common<const int, int>::type -> const int
      common<int, int &>::type -> int
      common<int &, int &>::type -> int &
      common<int &, int const &>::type -> int const &


      that is the result type should be the more restricted of the two. Is there a trait in the C++11 std that can do this or do I have to roll my own?



      My use case is that I have a something similar to



      template <typename T0, typename T1>
      struct Foo {

      BOOST_STATIC_ASSERT(
      std::is_same
      < typename std::decay<T0>::type
      , typename std::decay<T1>::type
      >::value
      );

      // I need to find T which is the most restrictive common
      // type between T0 and T1
      typedef typename common<T0,T1>::type T

      T0 t0;
      T1 t1;

      T choose(bool c){
      return c ? t0 : t1;
      }

      }






      c++ c++11 templates typetraits






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 21 '18 at 12:24









      max66

      36.4k74165




      36.4k74165










      asked Nov 21 '18 at 9:50









      bradgonesurfingbradgonesurfing

      16.3k1083151




      16.3k1083151
























          4 Answers
          4






          active

          oldest

          votes


















          2














          I am afraid that you need to roll your own. You can warp your types in a std::tuple, then pass it to std::common_type, e.g.



          #include <tuple>
          #include <type_traits>

          template <class T1, class T2>
          struct common {
          using type = typename std::tuple_element<0, typename std::common_type<std::tuple<T1>, std::tuple<T2>>::type>::type;
          };

          template <class T>
          struct common<const T, T> {
          using type = const T;
          };

          template <class T>
          struct common<T, const T> {
          using type = const T;
          };

          template <class T>
          struct common<const T, const T> {
          using type = const T;
          };

          int main()
          {
          static_assert(std::is_same<common<int, int>::type, int>::value, "");
          static_assert(std::is_same<common<const int, int>::type, const int>::value, "");
          static_assert(std::is_same<common<int, int &>::type, int>::value, "");
          static_assert(std::is_same<common<int &, int &>::type, int &>::value, "");
          static_assert(std::is_same<common<int &, int const &>::type, int const &>::value, "");
          return 0;
          }


          But you have to create special cases for const.






          share|improve this answer

































            2














            Taking inspiration from Oliv's solution, a possible C++11 version



            #include <utility>
            #include <type_traits>

            template <typename T1, typename T2>
            using cond_t = decltype(false ? std::declval<T1>() : std::declval<T2>());

            template <typename T1, typename T2>
            using common = typename std::conditional<
            std::is_reference<T1>::value || std::is_reference<T2>::value,
            cond_t<T1, T2>,
            typename std::remove_reference<cond_t<T1 &, T2 &>>::type>::type;

            int main()
            {
            using t1 = common<int,int>;
            using t2 = common<const int, int>;
            using t3 = common<int, int &>;
            using t4 = common<int &, int &>;
            using t5 = common<int &, int const &>;

            static_assert( std::is_same<t1, int>::value, "!" );
            static_assert( std::is_same<t2, int const>::value, "!" );
            static_assert( std::is_same<t3, int>::value, "!" );
            static_assert( std::is_same<t4, int &>::value, "!" );
            static_assert( std::is_same<t5, int const &>::value, "!" );
            }





            share|improve this answer


























            • I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted

              – bradgonesurfing
              Nov 21 '18 at 11:36





















            1














            In c++20 you could use common_reference, (there is an implementation in the range v3 library), but it needs some adaptation if none of the two types are reference:



            template<class T,class U>
            using common_t = conditional_t<is_reference_v<T> || is_reference_v<U>
            ,common_reference_t<T,U>
            ,remove_reference_t<common_reference_t<T&,U&>>>;





            share|improve this answer
























            • I need the solution for visual studio 2010 upwards but the answer is good info anyway :)

              – bradgonesurfing
              Nov 21 '18 at 10:27



















            0














            This can be hacked with decltype



            https://godbolt.org/z/7xEv7Z



            #include <type_traits>

            // Use it to display the actual generated type
            template <typename T> struct F;

            template <typename T0,typename T1>
            struct Common
            {
            typedef decltype(true ? ((T0)std::declval<T0>()) : ((T1)std::declval<T1>()) )
            type;
            };

            // Perform tests
            F<Common<int,int>::type> f0;
            F<Common<int &,int>::type> f1;
            F<Common<const int &, int &>::type> f2;
            F<Common<const int &, int>::type> f3;


            Gives the results as expected



            aggregate 'F<int> f0' has incomplete type and cannot be defined
            aggregate 'F<int> f1' has incomplete type and
            aggregate 'F<const int&> f2' has incomplete
            aggregate 'F<int> f3' has incomplete type and





            share|improve this answer


























            • I believe this will not give you the desired result for the case common<int, int>::type as declval will always return a reference and the deduced type is, thus, going to be a reference…

              – Michael Kenzel
              Nov 21 '18 at 10:23











            • @MichaelKenzel: I thought I saw your answer here before. Why did you delete it?

              – P.W
              Nov 21 '18 at 10:26











            • You are right. int,int give rvalue reference

              – bradgonesurfing
              Nov 21 '18 at 10:26











            • @P.W my answer was simply to use std::common_type which is, unfortunately, not correct as std::common_type will decay the arguments and just return plain int in all the cases above…

              – Michael Kenzel
              Nov 21 '18 at 10:30











            • @MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution

              – bradgonesurfing
              Nov 21 '18 at 10:41











            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53409292%2fis-there-a-c-trait-to-find-the-most-restricted-type-between-two-types-in-c%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            4 Answers
            4






            active

            oldest

            votes








            4 Answers
            4






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            2














            I am afraid that you need to roll your own. You can warp your types in a std::tuple, then pass it to std::common_type, e.g.



            #include <tuple>
            #include <type_traits>

            template <class T1, class T2>
            struct common {
            using type = typename std::tuple_element<0, typename std::common_type<std::tuple<T1>, std::tuple<T2>>::type>::type;
            };

            template <class T>
            struct common<const T, T> {
            using type = const T;
            };

            template <class T>
            struct common<T, const T> {
            using type = const T;
            };

            template <class T>
            struct common<const T, const T> {
            using type = const T;
            };

            int main()
            {
            static_assert(std::is_same<common<int, int>::type, int>::value, "");
            static_assert(std::is_same<common<const int, int>::type, const int>::value, "");
            static_assert(std::is_same<common<int, int &>::type, int>::value, "");
            static_assert(std::is_same<common<int &, int &>::type, int &>::value, "");
            static_assert(std::is_same<common<int &, int const &>::type, int const &>::value, "");
            return 0;
            }


            But you have to create special cases for const.






            share|improve this answer






























              2














              I am afraid that you need to roll your own. You can warp your types in a std::tuple, then pass it to std::common_type, e.g.



              #include <tuple>
              #include <type_traits>

              template <class T1, class T2>
              struct common {
              using type = typename std::tuple_element<0, typename std::common_type<std::tuple<T1>, std::tuple<T2>>::type>::type;
              };

              template <class T>
              struct common<const T, T> {
              using type = const T;
              };

              template <class T>
              struct common<T, const T> {
              using type = const T;
              };

              template <class T>
              struct common<const T, const T> {
              using type = const T;
              };

              int main()
              {
              static_assert(std::is_same<common<int, int>::type, int>::value, "");
              static_assert(std::is_same<common<const int, int>::type, const int>::value, "");
              static_assert(std::is_same<common<int, int &>::type, int>::value, "");
              static_assert(std::is_same<common<int &, int &>::type, int &>::value, "");
              static_assert(std::is_same<common<int &, int const &>::type, int const &>::value, "");
              return 0;
              }


              But you have to create special cases for const.






              share|improve this answer




























                2












                2








                2







                I am afraid that you need to roll your own. You can warp your types in a std::tuple, then pass it to std::common_type, e.g.



                #include <tuple>
                #include <type_traits>

                template <class T1, class T2>
                struct common {
                using type = typename std::tuple_element<0, typename std::common_type<std::tuple<T1>, std::tuple<T2>>::type>::type;
                };

                template <class T>
                struct common<const T, T> {
                using type = const T;
                };

                template <class T>
                struct common<T, const T> {
                using type = const T;
                };

                template <class T>
                struct common<const T, const T> {
                using type = const T;
                };

                int main()
                {
                static_assert(std::is_same<common<int, int>::type, int>::value, "");
                static_assert(std::is_same<common<const int, int>::type, const int>::value, "");
                static_assert(std::is_same<common<int, int &>::type, int>::value, "");
                static_assert(std::is_same<common<int &, int &>::type, int &>::value, "");
                static_assert(std::is_same<common<int &, int const &>::type, int const &>::value, "");
                return 0;
                }


                But you have to create special cases for const.






                share|improve this answer















                I am afraid that you need to roll your own. You can warp your types in a std::tuple, then pass it to std::common_type, e.g.



                #include <tuple>
                #include <type_traits>

                template <class T1, class T2>
                struct common {
                using type = typename std::tuple_element<0, typename std::common_type<std::tuple<T1>, std::tuple<T2>>::type>::type;
                };

                template <class T>
                struct common<const T, T> {
                using type = const T;
                };

                template <class T>
                struct common<T, const T> {
                using type = const T;
                };

                template <class T>
                struct common<const T, const T> {
                using type = const T;
                };

                int main()
                {
                static_assert(std::is_same<common<int, int>::type, int>::value, "");
                static_assert(std::is_same<common<const int, int>::type, const int>::value, "");
                static_assert(std::is_same<common<int, int &>::type, int>::value, "");
                static_assert(std::is_same<common<int &, int &>::type, int &>::value, "");
                static_assert(std::is_same<common<int &, int const &>::type, int const &>::value, "");
                return 0;
                }


                But you have to create special cases for const.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 21 '18 at 10:39

























                answered Nov 21 '18 at 10:17









                felixfelix

                1,473314




                1,473314

























                    2














                    Taking inspiration from Oliv's solution, a possible C++11 version



                    #include <utility>
                    #include <type_traits>

                    template <typename T1, typename T2>
                    using cond_t = decltype(false ? std::declval<T1>() : std::declval<T2>());

                    template <typename T1, typename T2>
                    using common = typename std::conditional<
                    std::is_reference<T1>::value || std::is_reference<T2>::value,
                    cond_t<T1, T2>,
                    typename std::remove_reference<cond_t<T1 &, T2 &>>::type>::type;

                    int main()
                    {
                    using t1 = common<int,int>;
                    using t2 = common<const int, int>;
                    using t3 = common<int, int &>;
                    using t4 = common<int &, int &>;
                    using t5 = common<int &, int const &>;

                    static_assert( std::is_same<t1, int>::value, "!" );
                    static_assert( std::is_same<t2, int const>::value, "!" );
                    static_assert( std::is_same<t3, int>::value, "!" );
                    static_assert( std::is_same<t4, int &>::value, "!" );
                    static_assert( std::is_same<t5, int const &>::value, "!" );
                    }





                    share|improve this answer


























                    • I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted

                      – bradgonesurfing
                      Nov 21 '18 at 11:36


















                    2














                    Taking inspiration from Oliv's solution, a possible C++11 version



                    #include <utility>
                    #include <type_traits>

                    template <typename T1, typename T2>
                    using cond_t = decltype(false ? std::declval<T1>() : std::declval<T2>());

                    template <typename T1, typename T2>
                    using common = typename std::conditional<
                    std::is_reference<T1>::value || std::is_reference<T2>::value,
                    cond_t<T1, T2>,
                    typename std::remove_reference<cond_t<T1 &, T2 &>>::type>::type;

                    int main()
                    {
                    using t1 = common<int,int>;
                    using t2 = common<const int, int>;
                    using t3 = common<int, int &>;
                    using t4 = common<int &, int &>;
                    using t5 = common<int &, int const &>;

                    static_assert( std::is_same<t1, int>::value, "!" );
                    static_assert( std::is_same<t2, int const>::value, "!" );
                    static_assert( std::is_same<t3, int>::value, "!" );
                    static_assert( std::is_same<t4, int &>::value, "!" );
                    static_assert( std::is_same<t5, int const &>::value, "!" );
                    }





                    share|improve this answer


























                    • I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted

                      – bradgonesurfing
                      Nov 21 '18 at 11:36
















                    2












                    2








                    2







                    Taking inspiration from Oliv's solution, a possible C++11 version



                    #include <utility>
                    #include <type_traits>

                    template <typename T1, typename T2>
                    using cond_t = decltype(false ? std::declval<T1>() : std::declval<T2>());

                    template <typename T1, typename T2>
                    using common = typename std::conditional<
                    std::is_reference<T1>::value || std::is_reference<T2>::value,
                    cond_t<T1, T2>,
                    typename std::remove_reference<cond_t<T1 &, T2 &>>::type>::type;

                    int main()
                    {
                    using t1 = common<int,int>;
                    using t2 = common<const int, int>;
                    using t3 = common<int, int &>;
                    using t4 = common<int &, int &>;
                    using t5 = common<int &, int const &>;

                    static_assert( std::is_same<t1, int>::value, "!" );
                    static_assert( std::is_same<t2, int const>::value, "!" );
                    static_assert( std::is_same<t3, int>::value, "!" );
                    static_assert( std::is_same<t4, int &>::value, "!" );
                    static_assert( std::is_same<t5, int const &>::value, "!" );
                    }





                    share|improve this answer















                    Taking inspiration from Oliv's solution, a possible C++11 version



                    #include <utility>
                    #include <type_traits>

                    template <typename T1, typename T2>
                    using cond_t = decltype(false ? std::declval<T1>() : std::declval<T2>());

                    template <typename T1, typename T2>
                    using common = typename std::conditional<
                    std::is_reference<T1>::value || std::is_reference<T2>::value,
                    cond_t<T1, T2>,
                    typename std::remove_reference<cond_t<T1 &, T2 &>>::type>::type;

                    int main()
                    {
                    using t1 = common<int,int>;
                    using t2 = common<const int, int>;
                    using t3 = common<int, int &>;
                    using t4 = common<int &, int &>;
                    using t5 = common<int &, int const &>;

                    static_assert( std::is_same<t1, int>::value, "!" );
                    static_assert( std::is_same<t2, int const>::value, "!" );
                    static_assert( std::is_same<t3, int>::value, "!" );
                    static_assert( std::is_same<t4, int &>::value, "!" );
                    static_assert( std::is_same<t5, int const &>::value, "!" );
                    }






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Nov 21 '18 at 12:23

























                    answered Nov 21 '18 at 11:00









                    max66max66

                    36.4k74165




                    36.4k74165













                    • I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted

                      – bradgonesurfing
                      Nov 21 '18 at 11:36





















                    • I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted

                      – bradgonesurfing
                      Nov 21 '18 at 11:36



















                    I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted

                    – bradgonesurfing
                    Nov 21 '18 at 11:36







                    I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted

                    – bradgonesurfing
                    Nov 21 '18 at 11:36













                    1














                    In c++20 you could use common_reference, (there is an implementation in the range v3 library), but it needs some adaptation if none of the two types are reference:



                    template<class T,class U>
                    using common_t = conditional_t<is_reference_v<T> || is_reference_v<U>
                    ,common_reference_t<T,U>
                    ,remove_reference_t<common_reference_t<T&,U&>>>;





                    share|improve this answer
























                    • I need the solution for visual studio 2010 upwards but the answer is good info anyway :)

                      – bradgonesurfing
                      Nov 21 '18 at 10:27
















                    1














                    In c++20 you could use common_reference, (there is an implementation in the range v3 library), but it needs some adaptation if none of the two types are reference:



                    template<class T,class U>
                    using common_t = conditional_t<is_reference_v<T> || is_reference_v<U>
                    ,common_reference_t<T,U>
                    ,remove_reference_t<common_reference_t<T&,U&>>>;





                    share|improve this answer
























                    • I need the solution for visual studio 2010 upwards but the answer is good info anyway :)

                      – bradgonesurfing
                      Nov 21 '18 at 10:27














                    1












                    1








                    1







                    In c++20 you could use common_reference, (there is an implementation in the range v3 library), but it needs some adaptation if none of the two types are reference:



                    template<class T,class U>
                    using common_t = conditional_t<is_reference_v<T> || is_reference_v<U>
                    ,common_reference_t<T,U>
                    ,remove_reference_t<common_reference_t<T&,U&>>>;





                    share|improve this answer













                    In c++20 you could use common_reference, (there is an implementation in the range v3 library), but it needs some adaptation if none of the two types are reference:



                    template<class T,class U>
                    using common_t = conditional_t<is_reference_v<T> || is_reference_v<U>
                    ,common_reference_t<T,U>
                    ,remove_reference_t<common_reference_t<T&,U&>>>;






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 21 '18 at 10:22









                    OlivOliv

                    9,3071957




                    9,3071957













                    • I need the solution for visual studio 2010 upwards but the answer is good info anyway :)

                      – bradgonesurfing
                      Nov 21 '18 at 10:27



















                    • I need the solution for visual studio 2010 upwards but the answer is good info anyway :)

                      – bradgonesurfing
                      Nov 21 '18 at 10:27

















                    I need the solution for visual studio 2010 upwards but the answer is good info anyway :)

                    – bradgonesurfing
                    Nov 21 '18 at 10:27





                    I need the solution for visual studio 2010 upwards but the answer is good info anyway :)

                    – bradgonesurfing
                    Nov 21 '18 at 10:27











                    0














                    This can be hacked with decltype



                    https://godbolt.org/z/7xEv7Z



                    #include <type_traits>

                    // Use it to display the actual generated type
                    template <typename T> struct F;

                    template <typename T0,typename T1>
                    struct Common
                    {
                    typedef decltype(true ? ((T0)std::declval<T0>()) : ((T1)std::declval<T1>()) )
                    type;
                    };

                    // Perform tests
                    F<Common<int,int>::type> f0;
                    F<Common<int &,int>::type> f1;
                    F<Common<const int &, int &>::type> f2;
                    F<Common<const int &, int>::type> f3;


                    Gives the results as expected



                    aggregate 'F<int> f0' has incomplete type and cannot be defined
                    aggregate 'F<int> f1' has incomplete type and
                    aggregate 'F<const int&> f2' has incomplete
                    aggregate 'F<int> f3' has incomplete type and





                    share|improve this answer


























                    • I believe this will not give you the desired result for the case common<int, int>::type as declval will always return a reference and the deduced type is, thus, going to be a reference…

                      – Michael Kenzel
                      Nov 21 '18 at 10:23











                    • @MichaelKenzel: I thought I saw your answer here before. Why did you delete it?

                      – P.W
                      Nov 21 '18 at 10:26











                    • You are right. int,int give rvalue reference

                      – bradgonesurfing
                      Nov 21 '18 at 10:26











                    • @P.W my answer was simply to use std::common_type which is, unfortunately, not correct as std::common_type will decay the arguments and just return plain int in all the cases above…

                      – Michael Kenzel
                      Nov 21 '18 at 10:30











                    • @MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution

                      – bradgonesurfing
                      Nov 21 '18 at 10:41
















                    0














                    This can be hacked with decltype



                    https://godbolt.org/z/7xEv7Z



                    #include <type_traits>

                    // Use it to display the actual generated type
                    template <typename T> struct F;

                    template <typename T0,typename T1>
                    struct Common
                    {
                    typedef decltype(true ? ((T0)std::declval<T0>()) : ((T1)std::declval<T1>()) )
                    type;
                    };

                    // Perform tests
                    F<Common<int,int>::type> f0;
                    F<Common<int &,int>::type> f1;
                    F<Common<const int &, int &>::type> f2;
                    F<Common<const int &, int>::type> f3;


                    Gives the results as expected



                    aggregate 'F<int> f0' has incomplete type and cannot be defined
                    aggregate 'F<int> f1' has incomplete type and
                    aggregate 'F<const int&> f2' has incomplete
                    aggregate 'F<int> f3' has incomplete type and





                    share|improve this answer


























                    • I believe this will not give you the desired result for the case common<int, int>::type as declval will always return a reference and the deduced type is, thus, going to be a reference…

                      – Michael Kenzel
                      Nov 21 '18 at 10:23











                    • @MichaelKenzel: I thought I saw your answer here before. Why did you delete it?

                      – P.W
                      Nov 21 '18 at 10:26











                    • You are right. int,int give rvalue reference

                      – bradgonesurfing
                      Nov 21 '18 at 10:26











                    • @P.W my answer was simply to use std::common_type which is, unfortunately, not correct as std::common_type will decay the arguments and just return plain int in all the cases above…

                      – Michael Kenzel
                      Nov 21 '18 at 10:30











                    • @MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution

                      – bradgonesurfing
                      Nov 21 '18 at 10:41














                    0












                    0








                    0







                    This can be hacked with decltype



                    https://godbolt.org/z/7xEv7Z



                    #include <type_traits>

                    // Use it to display the actual generated type
                    template <typename T> struct F;

                    template <typename T0,typename T1>
                    struct Common
                    {
                    typedef decltype(true ? ((T0)std::declval<T0>()) : ((T1)std::declval<T1>()) )
                    type;
                    };

                    // Perform tests
                    F<Common<int,int>::type> f0;
                    F<Common<int &,int>::type> f1;
                    F<Common<const int &, int &>::type> f2;
                    F<Common<const int &, int>::type> f3;


                    Gives the results as expected



                    aggregate 'F<int> f0' has incomplete type and cannot be defined
                    aggregate 'F<int> f1' has incomplete type and
                    aggregate 'F<const int&> f2' has incomplete
                    aggregate 'F<int> f3' has incomplete type and





                    share|improve this answer















                    This can be hacked with decltype



                    https://godbolt.org/z/7xEv7Z



                    #include <type_traits>

                    // Use it to display the actual generated type
                    template <typename T> struct F;

                    template <typename T0,typename T1>
                    struct Common
                    {
                    typedef decltype(true ? ((T0)std::declval<T0>()) : ((T1)std::declval<T1>()) )
                    type;
                    };

                    // Perform tests
                    F<Common<int,int>::type> f0;
                    F<Common<int &,int>::type> f1;
                    F<Common<const int &, int &>::type> f2;
                    F<Common<const int &, int>::type> f3;


                    Gives the results as expected



                    aggregate 'F<int> f0' has incomplete type and cannot be defined
                    aggregate 'F<int> f1' has incomplete type and
                    aggregate 'F<const int&> f2' has incomplete
                    aggregate 'F<int> f3' has incomplete type and






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Nov 21 '18 at 10:40

























                    answered Nov 21 '18 at 10:18









                    bradgonesurfingbradgonesurfing

                    16.3k1083151




                    16.3k1083151













                    • I believe this will not give you the desired result for the case common<int, int>::type as declval will always return a reference and the deduced type is, thus, going to be a reference…

                      – Michael Kenzel
                      Nov 21 '18 at 10:23











                    • @MichaelKenzel: I thought I saw your answer here before. Why did you delete it?

                      – P.W
                      Nov 21 '18 at 10:26











                    • You are right. int,int give rvalue reference

                      – bradgonesurfing
                      Nov 21 '18 at 10:26











                    • @P.W my answer was simply to use std::common_type which is, unfortunately, not correct as std::common_type will decay the arguments and just return plain int in all the cases above…

                      – Michael Kenzel
                      Nov 21 '18 at 10:30











                    • @MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution

                      – bradgonesurfing
                      Nov 21 '18 at 10:41



















                    • I believe this will not give you the desired result for the case common<int, int>::type as declval will always return a reference and the deduced type is, thus, going to be a reference…

                      – Michael Kenzel
                      Nov 21 '18 at 10:23











                    • @MichaelKenzel: I thought I saw your answer here before. Why did you delete it?

                      – P.W
                      Nov 21 '18 at 10:26











                    • You are right. int,int give rvalue reference

                      – bradgonesurfing
                      Nov 21 '18 at 10:26











                    • @P.W my answer was simply to use std::common_type which is, unfortunately, not correct as std::common_type will decay the arguments and just return plain int in all the cases above…

                      – Michael Kenzel
                      Nov 21 '18 at 10:30











                    • @MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution

                      – bradgonesurfing
                      Nov 21 '18 at 10:41

















                    I believe this will not give you the desired result for the case common<int, int>::type as declval will always return a reference and the deduced type is, thus, going to be a reference…

                    – Michael Kenzel
                    Nov 21 '18 at 10:23





                    I believe this will not give you the desired result for the case common<int, int>::type as declval will always return a reference and the deduced type is, thus, going to be a reference…

                    – Michael Kenzel
                    Nov 21 '18 at 10:23













                    @MichaelKenzel: I thought I saw your answer here before. Why did you delete it?

                    – P.W
                    Nov 21 '18 at 10:26





                    @MichaelKenzel: I thought I saw your answer here before. Why did you delete it?

                    – P.W
                    Nov 21 '18 at 10:26













                    You are right. int,int give rvalue reference

                    – bradgonesurfing
                    Nov 21 '18 at 10:26





                    You are right. int,int give rvalue reference

                    – bradgonesurfing
                    Nov 21 '18 at 10:26













                    @P.W my answer was simply to use std::common_type which is, unfortunately, not correct as std::common_type will decay the arguments and just return plain int in all the cases above…

                    – Michael Kenzel
                    Nov 21 '18 at 10:30





                    @P.W my answer was simply to use std::common_type which is, unfortunately, not correct as std::common_type will decay the arguments and just return plain int in all the cases above…

                    – Michael Kenzel
                    Nov 21 '18 at 10:30













                    @MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution

                    – bradgonesurfing
                    Nov 21 '18 at 10:41





                    @MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution

                    – bradgonesurfing
                    Nov 21 '18 at 10:41


















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53409292%2fis-there-a-c-trait-to-find-the-most-restricted-type-between-two-types-in-c%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    MongoDB - Not Authorized To Execute Command

                    How to fix TextFormField cause rebuild widget in Flutter

                    in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith