понедельник, 14 июля 2025 г.

Полиморфизм на основе стирания типа

 #include <iostream>  
 #include <vector>  
   
 class ConcreteStream1 {  
 private:  
   friend class IStream;  
   
   inline void foo() {   
     std::cout << "ConcreteStream1::foo" << std::endl;   
   }   
 };  
   
 class ConcreteStream2 {  
 private:  
   friend class IStream;  
   
   inline void foo() {   
     std::cout << "ConcreteStream2::foo" << std::endl;   
   }   
 };  
   
 class IStream {  
 public:  
   IStream(ConcreteStream1&& concreteStream1)  
   : streamType(StreamType::ConcreteStream1),  
    storage(Storage(std::forward<ConcreteStream1>(concreteStream1))) {}  
     
   IStream(ConcreteStream2&& concreteStream2)  
   : streamType(StreamType::ConcreteStream2),  
    storage(Storage(std::forward<ConcreteStream2>(concreteStream2))) {}  
   
   inline void foo() {  
     switch (streamType) {  
       case StreamType::ConcreteStream1:  
         storage.concreteStream1.foo();  
         break;  
       case StreamType::ConcreteStream2:  
         storage.concreteStream2.foo();  
         break;  
     }  
   }  
     
 private:  
   enum class StreamType {  
     ConcreteStream1,  
     ConcreteStream2,  
   };  
   
 private:  
   StreamType streamType;  
   union Storage{  
     Storage(ConcreteStream1&& concreteStream1)   
     : concreteStream1(std::move(concreteStream1)) {}  
     Storage(ConcreteStream2&& concreteStream2)   
     : concreteStream2(std::move(concreteStream2)) {}  
   
     ConcreteStream1 concreteStream1;  
     ConcreteStream2 concreteStream2;   
   } storage;  
 };  
   
 int main() {  
   std::vector<IStream> streams = { ConcreteStream1{}, ConcreteStream2{} };  
   
   streams[0].foo();  
   streams[1].foo();  
   
   return 0;   
 }  

воскресенье, 13 июля 2025 г.

Динамический полиморфизм vs Статический полиморфизм

Динамический полиморфизм
 #include <iostream>  
   
 class IStream {  
 public:  
   virtual ~IStream() = default;  
   virtual void foo() = 0;  
 };  
   
 class Stream : public IStream {  
 public:  
   void foo() override {  
     std::cout << "Stream::foo" << std::endl;  
   }  
 };  
   
 int main() {  
   IStream* stream = new Stream;  
   stream->foo();  
     
   return 0;   
 }  
Статический полиморфизм
 #include <iostream>  
   
 template<typename Stream>  
 class IStream : public Stream {  
 public:  
   inline void foo() {  
     return static_cast<Stream*>(this)->foo();  
   }  
 };   
   
 class Stream {  
 private:  
   friend class IStream<Stream>;  
     
   inline void foo() {  
     std::cout << "Stream::foo" << std::endl;  
   }  
 };  
     
 int main() {  
   IStream<Stream> stream;  
   stream.foo();  
   
   return 0;   
 }  

вторник, 9 января 2024 г.

Статический полиморфизм в С++

 #include <iostream>  
   
 // ------------------------ interface ------------------------  
 template<typename T>  
 struct IMeta  
 {  
   inline void foo() { return static_cast<T*>(this)->_foo(); }  
 };  
   
 template<typename T>  
 struct IPayload  
 {  
   inline void bar() { return static_cast<T*>(this)->_bar(); }  
 };  
   
 template<typename T>  
 struct IStream : public T, public IPayload<IStream<T>>, public IMeta<IStream<T>>  
 {  
   inline void baz() { return static_cast<T*>(this)->_baz(); }  
 };  
   
 // ------------------------ implementation ------------------------  
 template<typename T>  
 class Meta  
 {  
   friend class IMeta<IStream<T>>;  
   
   inline void _foo()  
      {  
           std::cout << "Meta::_foo::a = " << static_cast<T*>(this)->a << std::endl;  
      }  
 };  
   
 template<typename T>  
 class Payload  
 {  
   friend class IPayload<IStream<T>>;  
   
   inline void _bar()  
      {  
           std::cout << "Payload::_bar::a = " << static_cast<T*>(this)->a << std::endl;  
      }  
 };  
   
 class Stream : public Meta<Stream>, public Payload<Stream>  
 {  
   friend class IStream<Stream>;  
   friend class Meta<Stream>;  
   friend class Payload<Stream>;  
     
   uint64_t a = 3;  
   
   inline void _baz()  
      {  
           std::cout << "Stream::_baz::a = " << a << std::endl;  
      }  
 };  
   
 // ------------------------ usage ------------------------  
 int main()  
 {  
   IStream<Stream> stream;  
   
   stream.foo();  
   stream.bar();  
   stream.baz();  
   
   return 0;  
 }  
   

вторник, 2 января 2024 г.

С++17: автоопределение в runtime потока вызова для функции

 #include <iostream>  
 #include <thread>  
   
 void foo(unsigned char *data)  
 {  
   thread_local std::thread::id currentId(std::this_thread::get_id());  
   
   static std::thread::id id1(std::this_thread::get_id());  
   if (currentId == id1)  
   {   
     std::cout << "Thread1" << std::endl;  
     return;  
   }  
   
   static std::thread::id id2(std::this_thread::get_id());  
   if (currentId == id2)  
   {   
     std::cout << "Thread2" << std::endl;  
     return;  
   }  
   
   throw std::runtime_error("Thread is not processed!");  
 }  
   
 int main()  
 {  
   unsigned char *ptr;  
     
   std::thread thread1([&] { foo(ptr); });  
   std::thread thread2([&] { foo(ptr); });  
   //std::thread thread3([&] { foo(ptr); });  // will be an exception
   
   thread1.join();  
   thread2.join();  
   //thread3.join();  
   
   return 0;  
 }  

Перегруженный макрос

https://ideone.com/Kp59hv
 #include <stdio.h>  
 #include <stdint.h>  
 #include <stdlib.h>  
    
 /*   
  "Variadic macros tricks"  
    https://w...content-available-to-author-only...t.co/2014/11/25/variadic-macros-tricks/  
  "Is it possible to iterate over arguments in variadic macros?"  
    https://stackoverflow.com/questions/1872220/is-it-possible-to-iterate-over-arguments-in-variadic-macros/  
 */  
    
 #define _GET_OVERRIDE(ARG_1, ARG_2, ARG_3, ACTION, ...) ACTION  
    
 #define MALLOC(pMem)         \  
 (                  \  
  {                 \  
   pMem = malloc(sizeof(*pMem));  \  
   pMem ? 0 : 1;          \  
  }                 \  
 )  
    
 #define MALLOC_1(ARG_1, ...) MALLOC(ARG_1)  
 #define MALLOC_2(ARG_1, ...) MALLOC(ARG_1) | MALLOC_1(__VA_ARGS__)  
 #define MALLOC_3(ARG_1, ...) MALLOC(ARG_1) | MALLOC_2(__VA_ARGS__)  
    
 /* with return value */  
 #define MULTI_MALLOC(...) _GET_OVERRIDE(__VA_ARGS__, MALLOC_3, MALLOC_2, MALLOC_1)(__VA_ARGS__)  
    
 #define FREE(pMem)  \  
 {           \  
  free(pMem);     \  
  pMem = NULL;    \  
 }  
    
 #define FREE_1(ARG_1, ...) FREE(ARG_1)  
 #define FREE_2(ARG_1, ...) FREE(ARG_1) FREE_1(__VA_ARGS__)  
 #define FREE_3(ARG_1, ...) FREE(ARG_1) FREE_2(__VA_ARGS__)  
    
 /* without return value */  
 #define MULTI_FREE(...) _GET_OVERRIDE(__VA_ARGS__, FREE_3, FREE_2, FREE_1)(__VA_ARGS__)  
    
 int main(void)   
 {  
  uint16_t *pnShort = NULL;  
  uint32_t *pnInt  = NULL;  
  uint64_t *pnLong = NULL;  
    
  printf("start: %p, %p, %p\n", pnShort, pnInt, pnLong);  
    
  if ( MULTI_MALLOC(pnShort, pnInt, pnLong) ) { return 1; }  
  printf("3 args: %p, %p, %p\n", pnShort, pnInt, pnLong);  
  MULTI_FREE(pnShort, pnInt, pnLong);  
    
  if ( MULTI_MALLOC(pnShort, pnInt) ) { return 1; }  
  printf("2 args: %p, %p, %p\n", pnShort, pnInt, pnLong);  
  MULTI_FREE(pnShort, pnInt);  
    
  if ( MULTI_MALLOC(pnShort) ) { return 1; }  
  printf("1 arg: %p, %p, %p\n", pnShort, pnInt, pnLong);  
  MULTI_FREE(pnShort);  
    
  printf("finish: %p, %p, %p\n", pnShort, pnInt, pnLong);  
    
  return 0;  
Бен Клеменс "Язык С в XXI веке" гл.10 "Улучшенная структура" параграф "Векторизация функции" стр.218.

пятница, 27 мая 2022 г.

Вывод на экран значения числа в битовом виде в Си


#include <stdio.h
#include <stdint.h
#include <limits.h

#define BIT_PRINT(VALUE)                                    \
{                                                           \
    for(int i = sizeof(VALUE) * CHAR_BIT - 1; i >= 0; --i)  \
    {                                                       \
        printf("%c", ((VALUE) & (1LU << i)) ? '1' : '0');   \
    }                                                       \
    printf("\n");                                           \
}

#define BIT8_PRINT(VALUE)  BIT_PRINT((uint8_t )VALUE)
#define BIT16_PRINT(VALUE) BIT_PRINT((uint16_t)VALUE)
#define BIT32_PRINT(VALUE) BIT_PRINT((uint32_t)VALUE)
#define BIT64_PRINT(VALUE) BIT_PRINT((uint64_t)VALUE)

int main()  
{
    BIT8_PRINT(0x03);
    BIT16_PRINT(0x03);
    BIT32_PRINT(0x03);
    BIT64_PRINT(0x03);

    return 0;
}

среда, 22 мая 2019 г.