Why do type traits not work with types in namespace scope?What are POD types in C++?Why can templates only be...

Critique of timeline aesthetic

How did Captain America manage to do this?

How much cash can I safely carry into the USA and avoid civil forfeiture?

Elements other than carbon that can form many different compounds by bonding to themselves?

Why was the Spitfire's elliptical wing almost uncopied by other aircraft of World War 2?

a sore throat vs a strep throat vs strep throat

If a planet has 3 moons, is it possible to have triple Full/New Moons at once?

How to write a column outside the braces in a matrix?

Does holding a wand and speaking its command word count as V/S/M spell components?

Extension of 2-adic valuation to the real numbers

Is there an official tutorial for installing Ubuntu 18.04+ on a device with an SSD and an additional internal hard drive?

Disappearing left side of `aligned`

How do I deal with a coworker that keeps asking to make small superficial changes to a report, and it is seriously triggering my anxiety?

How can Republicans who favour free markets, consistently express anger when they don't like the outcome of that choice?

Binary Numbers Magic Trick

Can someone publish a story that happened to you?

Why was Germany not as successful as other Europeans in establishing overseas colonies?

Mjolnir's timeline from Thor's perspective

Can SQL Server create collisions in system generated constraint names?

Does Gita support doctrine of eternal cycle of birth and death for evil people?

Check if a string is entirely made of the same substring

A ​Note ​on ​N!

How could Tony Stark make this in Endgame?

Apply MapThread to all but one variable



Why do type traits not work with types in namespace scope?


What are POD types in C++?Why can templates only be implemented in the header file?Why is “using namespace std” considered bad practice?Why do we need virtual functions in C++?Can a local variable's memory be accessed outside its scope?Why are elementwise additions much faster in separate loops than in a combined loop?Why does changing 0.1f to 0 slow down performance by 10x?Why is reading lines from stdin much slower in C++ than Python?Why is it faster to process a sorted array than an unsorted array?Why should I use a pointer rather than the object itself?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







8















I'm designing a type register feature for my C++ serializing library.
But I encountered a strange problem about type traits.



I'm using Visual Studio 2017 with /std:c++latest.



#include <type_traits>

int reg(...);

template<class T>
constexpr bool is_known = !std::is_same_v<decltype(reg((T*)1)), int>;

//----- for type1 in global scope ------
struct type1 {};
void reg(type1 *);
static_assert(is_known<type1>); // success


//----- for type2 in namespace scope ----
namespace ns { struct type2 { }; }
void reg(ns::type2 *);
static_assert(is_known<ns::type2>); // fail!!!!


Static assert succeeds for type1, which is in global scope, but fails for namespace scope type2.



Why is there a difference?










share|improve this question









New contributor




shawn5013 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.



























    8















    I'm designing a type register feature for my C++ serializing library.
    But I encountered a strange problem about type traits.



    I'm using Visual Studio 2017 with /std:c++latest.



    #include <type_traits>

    int reg(...);

    template<class T>
    constexpr bool is_known = !std::is_same_v<decltype(reg((T*)1)), int>;

    //----- for type1 in global scope ------
    struct type1 {};
    void reg(type1 *);
    static_assert(is_known<type1>); // success


    //----- for type2 in namespace scope ----
    namespace ns { struct type2 { }; }
    void reg(ns::type2 *);
    static_assert(is_known<ns::type2>); // fail!!!!


    Static assert succeeds for type1, which is in global scope, but fails for namespace scope type2.



    Why is there a difference?










    share|improve this question









    New contributor




    shawn5013 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.























      8












      8








      8


      3






      I'm designing a type register feature for my C++ serializing library.
      But I encountered a strange problem about type traits.



      I'm using Visual Studio 2017 with /std:c++latest.



      #include <type_traits>

      int reg(...);

      template<class T>
      constexpr bool is_known = !std::is_same_v<decltype(reg((T*)1)), int>;

      //----- for type1 in global scope ------
      struct type1 {};
      void reg(type1 *);
      static_assert(is_known<type1>); // success


      //----- for type2 in namespace scope ----
      namespace ns { struct type2 { }; }
      void reg(ns::type2 *);
      static_assert(is_known<ns::type2>); // fail!!!!


      Static assert succeeds for type1, which is in global scope, but fails for namespace scope type2.



      Why is there a difference?










      share|improve this question









      New contributor




      shawn5013 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.












      I'm designing a type register feature for my C++ serializing library.
      But I encountered a strange problem about type traits.



      I'm using Visual Studio 2017 with /std:c++latest.



      #include <type_traits>

      int reg(...);

      template<class T>
      constexpr bool is_known = !std::is_same_v<decltype(reg((T*)1)), int>;

      //----- for type1 in global scope ------
      struct type1 {};
      void reg(type1 *);
      static_assert(is_known<type1>); // success


      //----- for type2 in namespace scope ----
      namespace ns { struct type2 { }; }
      void reg(ns::type2 *);
      static_assert(is_known<ns::type2>); // fail!!!!


      Static assert succeeds for type1, which is in global scope, but fails for namespace scope type2.



      Why is there a difference?







      c++






      share|improve this question









      New contributor




      shawn5013 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      shawn5013 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 1 hour ago









      Boann

      37.6k1291123




      37.6k1291123






      New contributor




      shawn5013 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 6 hours ago









      shawn5013shawn5013

      411




      411




      New contributor




      shawn5013 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      shawn5013 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      shawn5013 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.
























          2 Answers
          2






          active

          oldest

          votes


















          3














          TLDR The mechanism is known as the 2 phase lookup, and its rules are arcane. Rule of thumb is to always declare functions in the same namespace as the type it uses to avoid shenanigans.



          2 phase lookup occurs when there is a dependent name, at which point the name lookup is deferred to the point of instantiation. If the name is unqualified, the result of the lookup is the union of unqualified lookup at the point of definition and argument dependent lookup at the point of instantiation.



          Now what the hell does that even mean?



          Dependent name



          A name (eg a function name) is dependent if its meaning depends on a template parameter. In your case, reg depends on T because the argument type T* depends on T.



          Point of instantiation



          Template aliases aren't types, they represent an entire family of types. The type is said to be instantiated from the template when you actual give it a parameter. The point of instantiation is the place in the program where the template alias is first used with a actual parameter.



          Unqualified name



          A name is said to be unqualified if there is no scope resolution operator before it, eg reg is unqualified.



          Unqualified lookup



          Whenever a name appears in the program, its declaration has to be found, this is called name lookup. Unqualified lookup looks up the name from the scope where the name appears and searches outwards sequentially.



          Argument dependent lookup



          Also known as ADL, which is another lookup rule, it applies when the function name being looked up is unqualified and one of a function's arguments is a user defined type. It finds the name in the associated namespaces of the type. The associated namespaces includes the namespace where the type is defined, among many others.



          In conclusion, since is_known is defined before the following overloads of reg, unqualified lookup may only find reg(...). Since reg(ns::type2*) isn't within the associated namespace of ns::type2, it isn't found by ADL either.






          share|improve this answer































            3














            There are two sets of places examined when the lookup of reg((T*)) is done to find which reg is being referred to. The first is where the template is declared (where int reg(...) is visible), the second is ADL at the point where the template is first instantiated with a new type.



            ADL (argument dependent lookup) on ns::type2* does not examine the global namespace. It examines namespaces associated with that type, namely ns in this case. ADL does not examine namespaces "surrounding" or "above" associated namespaces.



            ADL for ::type1 does examine the global namespace.



            Templates are not macros. They don't act as if you copy-pasted the generated code at the point you instantiated it. MSVC used to treat templates more like macros, but they have increasingly come into compliance with the standard. The name they gave to their compliance efforts is "two phase name lookup" if you want to track why it broke in a specific version.



            The fix is to move reg into the namespace of ns::type2, or otherwise ensure that the namespace you define reg in is associated with the argument to reg (like use tag templates instead of pointers), or define reg before you define its use in decltype. Or something fancier; without underlying problem description I cannot guess.






            share|improve this answer


























              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
              });


              }
              });






              shawn5013 is a new contributor. Be nice, and check out our Code of Conduct.










              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55878310%2fwhy-do-type-traits-not-work-with-types-in-namespace-scope%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              3














              TLDR The mechanism is known as the 2 phase lookup, and its rules are arcane. Rule of thumb is to always declare functions in the same namespace as the type it uses to avoid shenanigans.



              2 phase lookup occurs when there is a dependent name, at which point the name lookup is deferred to the point of instantiation. If the name is unqualified, the result of the lookup is the union of unqualified lookup at the point of definition and argument dependent lookup at the point of instantiation.



              Now what the hell does that even mean?



              Dependent name



              A name (eg a function name) is dependent if its meaning depends on a template parameter. In your case, reg depends on T because the argument type T* depends on T.



              Point of instantiation



              Template aliases aren't types, they represent an entire family of types. The type is said to be instantiated from the template when you actual give it a parameter. The point of instantiation is the place in the program where the template alias is first used with a actual parameter.



              Unqualified name



              A name is said to be unqualified if there is no scope resolution operator before it, eg reg is unqualified.



              Unqualified lookup



              Whenever a name appears in the program, its declaration has to be found, this is called name lookup. Unqualified lookup looks up the name from the scope where the name appears and searches outwards sequentially.



              Argument dependent lookup



              Also known as ADL, which is another lookup rule, it applies when the function name being looked up is unqualified and one of a function's arguments is a user defined type. It finds the name in the associated namespaces of the type. The associated namespaces includes the namespace where the type is defined, among many others.



              In conclusion, since is_known is defined before the following overloads of reg, unqualified lookup may only find reg(...). Since reg(ns::type2*) isn't within the associated namespace of ns::type2, it isn't found by ADL either.






              share|improve this answer




























                3














                TLDR The mechanism is known as the 2 phase lookup, and its rules are arcane. Rule of thumb is to always declare functions in the same namespace as the type it uses to avoid shenanigans.



                2 phase lookup occurs when there is a dependent name, at which point the name lookup is deferred to the point of instantiation. If the name is unqualified, the result of the lookup is the union of unqualified lookup at the point of definition and argument dependent lookup at the point of instantiation.



                Now what the hell does that even mean?



                Dependent name



                A name (eg a function name) is dependent if its meaning depends on a template parameter. In your case, reg depends on T because the argument type T* depends on T.



                Point of instantiation



                Template aliases aren't types, they represent an entire family of types. The type is said to be instantiated from the template when you actual give it a parameter. The point of instantiation is the place in the program where the template alias is first used with a actual parameter.



                Unqualified name



                A name is said to be unqualified if there is no scope resolution operator before it, eg reg is unqualified.



                Unqualified lookup



                Whenever a name appears in the program, its declaration has to be found, this is called name lookup. Unqualified lookup looks up the name from the scope where the name appears and searches outwards sequentially.



                Argument dependent lookup



                Also known as ADL, which is another lookup rule, it applies when the function name being looked up is unqualified and one of a function's arguments is a user defined type. It finds the name in the associated namespaces of the type. The associated namespaces includes the namespace where the type is defined, among many others.



                In conclusion, since is_known is defined before the following overloads of reg, unqualified lookup may only find reg(...). Since reg(ns::type2*) isn't within the associated namespace of ns::type2, it isn't found by ADL either.






                share|improve this answer


























                  3












                  3








                  3







                  TLDR The mechanism is known as the 2 phase lookup, and its rules are arcane. Rule of thumb is to always declare functions in the same namespace as the type it uses to avoid shenanigans.



                  2 phase lookup occurs when there is a dependent name, at which point the name lookup is deferred to the point of instantiation. If the name is unqualified, the result of the lookup is the union of unqualified lookup at the point of definition and argument dependent lookup at the point of instantiation.



                  Now what the hell does that even mean?



                  Dependent name



                  A name (eg a function name) is dependent if its meaning depends on a template parameter. In your case, reg depends on T because the argument type T* depends on T.



                  Point of instantiation



                  Template aliases aren't types, they represent an entire family of types. The type is said to be instantiated from the template when you actual give it a parameter. The point of instantiation is the place in the program where the template alias is first used with a actual parameter.



                  Unqualified name



                  A name is said to be unqualified if there is no scope resolution operator before it, eg reg is unqualified.



                  Unqualified lookup



                  Whenever a name appears in the program, its declaration has to be found, this is called name lookup. Unqualified lookup looks up the name from the scope where the name appears and searches outwards sequentially.



                  Argument dependent lookup



                  Also known as ADL, which is another lookup rule, it applies when the function name being looked up is unqualified and one of a function's arguments is a user defined type. It finds the name in the associated namespaces of the type. The associated namespaces includes the namespace where the type is defined, among many others.



                  In conclusion, since is_known is defined before the following overloads of reg, unqualified lookup may only find reg(...). Since reg(ns::type2*) isn't within the associated namespace of ns::type2, it isn't found by ADL either.






                  share|improve this answer













                  TLDR The mechanism is known as the 2 phase lookup, and its rules are arcane. Rule of thumb is to always declare functions in the same namespace as the type it uses to avoid shenanigans.



                  2 phase lookup occurs when there is a dependent name, at which point the name lookup is deferred to the point of instantiation. If the name is unqualified, the result of the lookup is the union of unqualified lookup at the point of definition and argument dependent lookup at the point of instantiation.



                  Now what the hell does that even mean?



                  Dependent name



                  A name (eg a function name) is dependent if its meaning depends on a template parameter. In your case, reg depends on T because the argument type T* depends on T.



                  Point of instantiation



                  Template aliases aren't types, they represent an entire family of types. The type is said to be instantiated from the template when you actual give it a parameter. The point of instantiation is the place in the program where the template alias is first used with a actual parameter.



                  Unqualified name



                  A name is said to be unqualified if there is no scope resolution operator before it, eg reg is unqualified.



                  Unqualified lookup



                  Whenever a name appears in the program, its declaration has to be found, this is called name lookup. Unqualified lookup looks up the name from the scope where the name appears and searches outwards sequentially.



                  Argument dependent lookup



                  Also known as ADL, which is another lookup rule, it applies when the function name being looked up is unqualified and one of a function's arguments is a user defined type. It finds the name in the associated namespaces of the type. The associated namespaces includes the namespace where the type is defined, among many others.



                  In conclusion, since is_known is defined before the following overloads of reg, unqualified lookup may only find reg(...). Since reg(ns::type2*) isn't within the associated namespace of ns::type2, it isn't found by ADL either.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 5 hours ago









                  Passer ByPasser By

                  10.4k42662




                  10.4k42662

























                      3














                      There are two sets of places examined when the lookup of reg((T*)) is done to find which reg is being referred to. The first is where the template is declared (where int reg(...) is visible), the second is ADL at the point where the template is first instantiated with a new type.



                      ADL (argument dependent lookup) on ns::type2* does not examine the global namespace. It examines namespaces associated with that type, namely ns in this case. ADL does not examine namespaces "surrounding" or "above" associated namespaces.



                      ADL for ::type1 does examine the global namespace.



                      Templates are not macros. They don't act as if you copy-pasted the generated code at the point you instantiated it. MSVC used to treat templates more like macros, but they have increasingly come into compliance with the standard. The name they gave to their compliance efforts is "two phase name lookup" if you want to track why it broke in a specific version.



                      The fix is to move reg into the namespace of ns::type2, or otherwise ensure that the namespace you define reg in is associated with the argument to reg (like use tag templates instead of pointers), or define reg before you define its use in decltype. Or something fancier; without underlying problem description I cannot guess.






                      share|improve this answer






























                        3














                        There are two sets of places examined when the lookup of reg((T*)) is done to find which reg is being referred to. The first is where the template is declared (where int reg(...) is visible), the second is ADL at the point where the template is first instantiated with a new type.



                        ADL (argument dependent lookup) on ns::type2* does not examine the global namespace. It examines namespaces associated with that type, namely ns in this case. ADL does not examine namespaces "surrounding" or "above" associated namespaces.



                        ADL for ::type1 does examine the global namespace.



                        Templates are not macros. They don't act as if you copy-pasted the generated code at the point you instantiated it. MSVC used to treat templates more like macros, but they have increasingly come into compliance with the standard. The name they gave to their compliance efforts is "two phase name lookup" if you want to track why it broke in a specific version.



                        The fix is to move reg into the namespace of ns::type2, or otherwise ensure that the namespace you define reg in is associated with the argument to reg (like use tag templates instead of pointers), or define reg before you define its use in decltype. Or something fancier; without underlying problem description I cannot guess.






                        share|improve this answer




























                          3












                          3








                          3







                          There are two sets of places examined when the lookup of reg((T*)) is done to find which reg is being referred to. The first is where the template is declared (where int reg(...) is visible), the second is ADL at the point where the template is first instantiated with a new type.



                          ADL (argument dependent lookup) on ns::type2* does not examine the global namespace. It examines namespaces associated with that type, namely ns in this case. ADL does not examine namespaces "surrounding" or "above" associated namespaces.



                          ADL for ::type1 does examine the global namespace.



                          Templates are not macros. They don't act as if you copy-pasted the generated code at the point you instantiated it. MSVC used to treat templates more like macros, but they have increasingly come into compliance with the standard. The name they gave to their compliance efforts is "two phase name lookup" if you want to track why it broke in a specific version.



                          The fix is to move reg into the namespace of ns::type2, or otherwise ensure that the namespace you define reg in is associated with the argument to reg (like use tag templates instead of pointers), or define reg before you define its use in decltype. Or something fancier; without underlying problem description I cannot guess.






                          share|improve this answer















                          There are two sets of places examined when the lookup of reg((T*)) is done to find which reg is being referred to. The first is where the template is declared (where int reg(...) is visible), the second is ADL at the point where the template is first instantiated with a new type.



                          ADL (argument dependent lookup) on ns::type2* does not examine the global namespace. It examines namespaces associated with that type, namely ns in this case. ADL does not examine namespaces "surrounding" or "above" associated namespaces.



                          ADL for ::type1 does examine the global namespace.



                          Templates are not macros. They don't act as if you copy-pasted the generated code at the point you instantiated it. MSVC used to treat templates more like macros, but they have increasingly come into compliance with the standard. The name they gave to their compliance efforts is "two phase name lookup" if you want to track why it broke in a specific version.



                          The fix is to move reg into the namespace of ns::type2, or otherwise ensure that the namespace you define reg in is associated with the argument to reg (like use tag templates instead of pointers), or define reg before you define its use in decltype. Or something fancier; without underlying problem description I cannot guess.







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited 1 hour ago









                          Alan Birtles

                          10.1k11235




                          10.1k11235










                          answered 5 hours ago









                          Yakk - Adam NevraumontYakk - Adam Nevraumont

                          190k21200386




                          190k21200386






















                              shawn5013 is a new contributor. Be nice, and check out our Code of Conduct.










                              draft saved

                              draft discarded


















                              shawn5013 is a new contributor. Be nice, and check out our Code of Conduct.













                              shawn5013 is a new contributor. Be nice, and check out our Code of Conduct.












                              shawn5013 is a new contributor. Be nice, and check out our Code of Conduct.
















                              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%2f55878310%2fwhy-do-type-traits-not-work-with-types-in-namespace-scope%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

                              Щит и меч (фильм) Содержание Названия серий | Сюжет |...

                              is 'sed' thread safeWhat should someone know about using Python scripts in the shell?Nexenta bash script uses...

                              Meter-Bus Содержание Параметры шины | Стандартизация |...