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?

Catholic vs Protestant Support for Nazism in Germany

Manager is threatning to grade me poorly if I don't complete the project

How do I tell my manager that his code review comment is wrong?

Did we get closer to another plane than we were supposed to, or was the pilot just protecting our delicate sensibilities?

What happens if I start too many background jobs?

Do I have to make someone coauthor if he/she solves a problem in StackExchange, asked by myself, which is later used in my paper?

Is Cola "probably the best-known" Latin word in the world? If not, which might it be?

Junior developer struggles: how to communicate with management?

Pressure inside an infinite ocean?

What are the differences between credential stuffing and password spraying?

Father and Son and Grandsons

Point of the the Dothraki's attack in GoT S8E3?

Why was the battle set up *outside* Winterfell?

Are we obligated to aspire to be Talmidei Chachamim?

Type-check an expression

Python password manager

Is it cheaper to drop cargo than to land it?

If Earth is tilted, why is Polaris always above the same spot?

To customize a predefined symbol with different colors

I caught several of my students plagiarizing. Could it be my fault as a teacher?

What does this colon mean? It is not labeling, it is not ternary operator

Was Unix ever a single-user OS?

What was the state of the German rail system in 1944?

Is one octave above tonic also considered as tonic?



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 Apr 27 at 12:39









      Boann

      37.7k1291123




      37.7k1291123






      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 Apr 27 at 7:28









      shawn5013shawn5013

      433




      433




      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


















          5














          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

























          • Thanks. I almost understand. I've been used to the non-conformance way how MSVC parsing templates. If I remove the /permissive- switch, the code above works, but it may go wrong one day in the feature, and further more, it's not cross-platform. In my case, moving reg into namespace ns or defining reg before definition of is_known is not suitable. What do you mean by tag templates?

            – shawn5013
            2 days ago











          • @shawn Quite simply, nothing (besides other namespaces and legacy stuff) belongs in the global namespace. But if you have a question on how to do something, ask it using the "ask question" button not "post comment" button. Your question above asked why there was a different behaviour, not how to solve your problem (and a question about your problem would descibe the underlying problem, as well as the attempted solition and the bug in the attempted solution -- this one asks "what caused the bug"). Comments are not suitable for a Q&A.

            – Yakk - Adam Nevraumont
            2 days ago



















          5














          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 give it a parameter. The point of instantiation is the place in the program where the template alias is first used with an 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

























          • Thank you very much! I think I need a little more time to understand the complicated name lookup rules when using templates. And do you know how to implement the feature? Intrusive way like moving reg(ns::type2*) into namespace ns is not suitable.

            – shawn5013
            2 days ago











          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









          5














          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

























          • Thanks. I almost understand. I've been used to the non-conformance way how MSVC parsing templates. If I remove the /permissive- switch, the code above works, but it may go wrong one day in the feature, and further more, it's not cross-platform. In my case, moving reg into namespace ns or defining reg before definition of is_known is not suitable. What do you mean by tag templates?

            – shawn5013
            2 days ago











          • @shawn Quite simply, nothing (besides other namespaces and legacy stuff) belongs in the global namespace. But if you have a question on how to do something, ask it using the "ask question" button not "post comment" button. Your question above asked why there was a different behaviour, not how to solve your problem (and a question about your problem would descibe the underlying problem, as well as the attempted solition and the bug in the attempted solution -- this one asks "what caused the bug"). Comments are not suitable for a Q&A.

            – Yakk - Adam Nevraumont
            2 days ago
















          5














          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

























          • Thanks. I almost understand. I've been used to the non-conformance way how MSVC parsing templates. If I remove the /permissive- switch, the code above works, but it may go wrong one day in the feature, and further more, it's not cross-platform. In my case, moving reg into namespace ns or defining reg before definition of is_known is not suitable. What do you mean by tag templates?

            – shawn5013
            2 days ago











          • @shawn Quite simply, nothing (besides other namespaces and legacy stuff) belongs in the global namespace. But if you have a question on how to do something, ask it using the "ask question" button not "post comment" button. Your question above asked why there was a different behaviour, not how to solve your problem (and a question about your problem would descibe the underlying problem, as well as the attempted solition and the bug in the attempted solution -- this one asks "what caused the bug"). Comments are not suitable for a Q&A.

            – Yakk - Adam Nevraumont
            2 days ago














          5












          5








          5







          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 Apr 27 at 12:44









          Alan Birtles

          10.2k11235




          10.2k11235










          answered Apr 27 at 8:52









          Yakk - Adam NevraumontYakk - Adam Nevraumont

          190k21200386




          190k21200386












          • Thanks. I almost understand. I've been used to the non-conformance way how MSVC parsing templates. If I remove the /permissive- switch, the code above works, but it may go wrong one day in the feature, and further more, it's not cross-platform. In my case, moving reg into namespace ns or defining reg before definition of is_known is not suitable. What do you mean by tag templates?

            – shawn5013
            2 days ago











          • @shawn Quite simply, nothing (besides other namespaces and legacy stuff) belongs in the global namespace. But if you have a question on how to do something, ask it using the "ask question" button not "post comment" button. Your question above asked why there was a different behaviour, not how to solve your problem (and a question about your problem would descibe the underlying problem, as well as the attempted solition and the bug in the attempted solution -- this one asks "what caused the bug"). Comments are not suitable for a Q&A.

            – Yakk - Adam Nevraumont
            2 days ago


















          • Thanks. I almost understand. I've been used to the non-conformance way how MSVC parsing templates. If I remove the /permissive- switch, the code above works, but it may go wrong one day in the feature, and further more, it's not cross-platform. In my case, moving reg into namespace ns or defining reg before definition of is_known is not suitable. What do you mean by tag templates?

            – shawn5013
            2 days ago











          • @shawn Quite simply, nothing (besides other namespaces and legacy stuff) belongs in the global namespace. But if you have a question on how to do something, ask it using the "ask question" button not "post comment" button. Your question above asked why there was a different behaviour, not how to solve your problem (and a question about your problem would descibe the underlying problem, as well as the attempted solition and the bug in the attempted solution -- this one asks "what caused the bug"). Comments are not suitable for a Q&A.

            – Yakk - Adam Nevraumont
            2 days ago

















          Thanks. I almost understand. I've been used to the non-conformance way how MSVC parsing templates. If I remove the /permissive- switch, the code above works, but it may go wrong one day in the feature, and further more, it's not cross-platform. In my case, moving reg into namespace ns or defining reg before definition of is_known is not suitable. What do you mean by tag templates?

          – shawn5013
          2 days ago





          Thanks. I almost understand. I've been used to the non-conformance way how MSVC parsing templates. If I remove the /permissive- switch, the code above works, but it may go wrong one day in the feature, and further more, it's not cross-platform. In my case, moving reg into namespace ns or defining reg before definition of is_known is not suitable. What do you mean by tag templates?

          – shawn5013
          2 days ago













          @shawn Quite simply, nothing (besides other namespaces and legacy stuff) belongs in the global namespace. But if you have a question on how to do something, ask it using the "ask question" button not "post comment" button. Your question above asked why there was a different behaviour, not how to solve your problem (and a question about your problem would descibe the underlying problem, as well as the attempted solition and the bug in the attempted solution -- this one asks "what caused the bug"). Comments are not suitable for a Q&A.

          – Yakk - Adam Nevraumont
          2 days ago






          @shawn Quite simply, nothing (besides other namespaces and legacy stuff) belongs in the global namespace. But if you have a question on how to do something, ask it using the "ask question" button not "post comment" button. Your question above asked why there was a different behaviour, not how to solve your problem (and a question about your problem would descibe the underlying problem, as well as the attempted solition and the bug in the attempted solution -- this one asks "what caused the bug"). Comments are not suitable for a Q&A.

          – Yakk - Adam Nevraumont
          2 days ago














          5














          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 give it a parameter. The point of instantiation is the place in the program where the template alias is first used with an 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

























          • Thank you very much! I think I need a little more time to understand the complicated name lookup rules when using templates. And do you know how to implement the feature? Intrusive way like moving reg(ns::type2*) into namespace ns is not suitable.

            – shawn5013
            2 days ago















          5














          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 give it a parameter. The point of instantiation is the place in the program where the template alias is first used with an 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

























          • Thank you very much! I think I need a little more time to understand the complicated name lookup rules when using templates. And do you know how to implement the feature? Intrusive way like moving reg(ns::type2*) into namespace ns is not suitable.

            – shawn5013
            2 days ago













          5












          5








          5







          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 give it a parameter. The point of instantiation is the place in the program where the template alias is first used with an 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 give it a parameter. The point of instantiation is the place in the program where the template alias is first used with an 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








          edited Apr 27 at 20:53

























          answered Apr 27 at 9:06









          Passer ByPasser By

          10.5k42662




          10.5k42662












          • Thank you very much! I think I need a little more time to understand the complicated name lookup rules when using templates. And do you know how to implement the feature? Intrusive way like moving reg(ns::type2*) into namespace ns is not suitable.

            – shawn5013
            2 days ago

















          • Thank you very much! I think I need a little more time to understand the complicated name lookup rules when using templates. And do you know how to implement the feature? Intrusive way like moving reg(ns::type2*) into namespace ns is not suitable.

            – shawn5013
            2 days ago
















          Thank you very much! I think I need a little more time to understand the complicated name lookup rules when using templates. And do you know how to implement the feature? Intrusive way like moving reg(ns::type2*) into namespace ns is not suitable.

          – shawn5013
          2 days ago





          Thank you very much! I think I need a little more time to understand the complicated name lookup rules when using templates. And do you know how to implement the feature? Intrusive way like moving reg(ns::type2*) into namespace ns is not suitable.

          – shawn5013
          2 days ago










          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

          Grendel Contents Story Scholarship Depictions Notes References Navigation menu10.1093/notesj/gjn112Berserkeree

          Area configuration aggregation error after install Porto themeMagento 2.1 CE Installed but front/backend not loading/workingCSS not loading on page within Magento 2 pageCannot install module in Magento 2no commands defined in the “setup” namespace. in Magento2Magento 2: Static files are present but shows 404Why do i have to always run the commands to clean cache in Magento 2.1.8?Failure reason: 'Unable to unserialize value.'Error 500 after magento migrationIn production mode the site does not loadMagento 2 : Error 500 after installing

          Middle Expansion Olielle Resaix Definition: Uttering songs of triumph shouting with joy triumphant exulting Sejunction Journal 붙다 달 고급 품목 외출 The stretch trades the screeching tin. Definition: The act of speaking with a drawl a drawl Cough Sand Definition: An uproar a quarrel a noisy outbreak Shake Iron Publicize Horse House Baby 사과 Resaix Flaggy Jelly Temporary Unequaled Puppet A drop in the bucket Shrew 성격 회원 성질 미팅 The burn frames the tacky quality. Materialistic The smoke reduces the way. Yammoe Nondescript Cheek 얼굴 배 약하다 날리다 타다 The illegal country shows the iron. Help Rule Drearien Smoke Teaching Meaty Wasp Abraham Lincoln Jaws 진심 수리하다 Size Cork Idea Convert Think Lark John Lennon 거울 청소 군 추천하다 아이스크림