home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 32,991 of 33,346   
   =?ISO-8859-1?Q?Daniel_Kr=FCgler?= to Ryan   
   Re: Incorrect stream operator called for   
   22 Apr 13 15:49:21   
   
   From: daniel.kruegler@googlemail.com   
      
   On 2013-04-18 22:49, Ryan wrote:   
   > On Thursday, April 18, 2013 7:00:02 AM UTC-7, SG wrote:   
   >> The compiler will see your operator<< but the problem is that it won't   
   >> try to figure out what T is because none of your function's parameter   
   >> types are "deducible contexts" with respect to T. At the op<< call   
   >> site you have a stream on the left hand side and an int on the right   
   >> hand side. Should the compiler now try every possible T to see whether   
   >> B::foo is an int? What if there are many such Ts like in your case?   
   >> B::foo is an int as well as B::foo is an int.   
   >   
   > So what do I need to do to get a "deducible context"?   
      
   It depends what you want to realize. If I understand your code pattern   
   correctly, I don't see any way of deducing the type of T here from the   
   type of the member B::m_Bs: The type of B::m_Bs is some unique   
   type Bs' derived from A::As, but this is not sufficient information to   
   deduce the template Parameter T of the *nesting* type B, because it   
   is not the template form of B that makes the concrete nested type   
   unique from other nested types such as   
      
   class K {   
      public:   
        struct Bs : public A::As {} m_Bs;   
   };   
      
   Assume you have   
      
   int main()   
   {   
      K k;   
      std::cout << k.m_Bs << std::endl;   
   }   
      
   How should the compiler "know" that the provided argument value that has   
   type K::Bs is in a different sense some unique derived type compared to   
   some instance of B::m_Bs.   
      
   > In my code   
   > the T types being passed to B are classes that have their own op<<   
   > that I want to call.   
      
   I don't understand what you mean by "the T types being passed to B",   
   because you never assign anything to B. Nor do I understand what you are   
   trying to realize here, because your overload   
      
   template    
   std::ostream & operator<<(std::ostream & stream, typename B::Bs   
   const& value);   
      
   ignores any aspects of the template parameter T of the B template.   
      
   If you want to discriminate "class types named Bs that are contained in   
   a B template from other derived classes of A::As", you have to make this   
   special uniqueness testable. Here is a simple sketch to demonstrate how   
   this can be done:   
      
   #include    
      
   struct B_tag{};   
      
   template    
   class B : public A {   
      public:   
        struct Bs : A::As, B_tag {} m_Bs;   
   };   
      
   template   
   struct has_B_marker   
   {   
     // Add further constraints here:   
     static const bool value = std::is_base_of::value &&   
       std::is_base_of::value;   
   };   
      
   template    
   typename std::enable_if::value, std::ostream&>::type   
   operator<<(std::ostream& stream, const T& value) {   
      stream << static_cast(value) << std::endl;   
      stream << "Class Bs" << std::endl;   
      return stream;   
   }   
      
   If you also need to deduce the actual template parameter type T, you can   
   extend the approach to use a template marker such as in the following   
   example:   
      
   #include    
   #include    
      
   template   
   struct Bs : A::As {};   
      
   template    
   class B : public A {   
      public:   
        typedef ::Bs Bs;   
        Bs m_Bs;   
   };   
      
   template   
   struct is_Bs_impl   
   {   
     static const bool value = false;   
     typedef void param_type;   
   };   
      
   template   
   struct is_Bs_impl>   
   {   
     static const bool value = true;   
     typedef T param_type;   
   };   
      
   template   
   struct is_Bs   
   {   
   private:   
     typedef is_Bs_impl<   
       typename std::remove_cv::type>::type   
     > impl_type;   
   public:   
     static const bool value = impl_type::value;   
     typedef typename impl_type::param_type param_type;   
   };   
      
   template   
   struct is_marked_Bs   
   {   
     // Add further constraints here:   
     static const bool value = is_Bs::value &&   
       std::is_base_of::value;   
   };   
      
   template    
   typename std::enable_if::value, std::ostream&>::type   
   operator<<(std::ostream& stream, const T& value) {   
      stream << static_cast(value) << std::endl;   
      stream << "Class Bs" << std::endl;   
      stream << "T: " << typeid(typename is_Bs::param_type).name() <<   
   std::endl;   
      return stream;   
   }   
      
   HTH & Greetings from Bremen,   
      
   Daniel Krügler   
      
      
   --   
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca