Programing

__CURTOR__ 전 프로세서 매크로를 사용한 적이 있는 사람이 있는가?

c10106 2022. 4. 26. 19:41
반응형

__CURTOR__ 전 프로세서 매크로를 사용한 적이 있는 사람이 있는가?

__COUNTER__기호는 VC++와 GCC에서 제공하며, 사용할 때마다 음이 아닌 적분 값이 증가한다.

누가 써 본 적이 있는지, 표준화할 만한 가치가 있을 만한 것인지에 대해 알고 싶다.

__COUNTER__독특한 이름이 필요한 곳이라면 어디든 유용하다.나는 그것을 RAII 스타일 잠금장치와 스택에 광범위하게 사용해 왔다.고려 사항:

struct TLock
{
  void Lock();
  void Unlock();
}
g_Lock1, g_Lock2;

struct TLockUse
{
  TLockUse( TLock &lock ):m_Lock(lock){ m_Lock.Lock(); }
  ~TLockUse(){ m_Lock.Unlock(); }

  TLock &m_Lock;
};

void DoSomething()
{
  TLockUse lock_use1( g_Lock1 );
  TLockUse lock_use2( g_Lock2 );
  // ...
}

자물쇠의 용도에 이름을 붙이는 것은 지루하고, 만약 그것들이 모두 블록의 맨 위에 선언되지 않는다면, 심지어 오류의 원인이 될 수도 있다.지금 하고 있는지 어떻게 알아?lock_use4또는lock_use11 나는 가 없다 또한 네임스페이스의 불필요한 오염이다 - 나는 결코 이름별로 자물쇠 사용물체를 언급할 필요가 없다.그래서 나는 사용한다.__COUNTER__:

#define CONCAT_IMPL( x, y ) x##y
#define MACRO_CONCAT( x, y ) CONCAT_IMPL( x, y )
#define USE_LOCK( lock ) TLockUse MACRO_CONCAT( LockUse, __COUNTER__ )( lock )

void DoSomething2()
{
  USE_LOCK( g_Lock1 );
  USE_LOCK( g_Lock2 );
  // ...
}

하지만 내가 물체 잠금 장치라고 불렀다는 사실에 집착하지 마라. 짝을 지어 불러야 하는 어떤 기능도 이 패턴에 들어맞는다.주어진 블록에서 동일한 "잠금"을 여러 번 사용할 수도 있다.

누가 써본 적이 있는지 알고 싶은데

네, 하지만 이번 Q&A의 많은 사례에서 보시다시피,__LINE__표준화되어 있는 , 또한 대부분의 경우 충분할 것이다.

__COUNTER__횟수가 매번 1회씩 증가하거나 여러 번 연속성을 가져야 하는 경우에만 정말로 필요하다.#include파일들

표준화할 만한 가치가 있는 것인지?

__COUNTER__,와는 달리__LINE__는 어떤 헤더 파일이 포함되고 어떤 순서에 따라 달라지기 때문에 매우 위험하다.만약 둘이면.cpp파일(파일)은 사용하는 헤더 파일을 포함한다.__COUNTER__그러나 헤더 파일은 다른 인스턴스에서 서로 다른 카운트 시퀀스를 얻으며, 동일한 항목에 대한 다른 정의를 사용할 수 있으며 단일 정의 규칙을 위반할 수 있다.

단일 정의 규칙 위반은 매우 잡기 어렵고 잠재적으로 버그와 보안 위험을 발생시킬 수 있다.의 몇 가지 사용 사례__COUNTER__확장성의 단점과 부족을 실제로 능가하지는 마십시오.

비록 당신이 사용하지 않는 코드를 발송하지 않더라도__COUNTER__, 열거 시퀀스를 프로토타입화할 때 유용할 수 있으며, 멤버십이 구체화되기 전에 이름을 할당하는 번거로움을 덜 수 있다.

xCover 코드 적용 범위 라이브러리에서 실행이 통과하는 라인을 표시하고 적용되지 않는 라인을 찾는데 사용되며,

클래스 유형 ID 생성 중(C++)

써본 적이 있다.__COUNTER__객체 지향 게임에서 엔티티 & 콜라이더에 대한 타입 ID를 자동으로 생성한다.

이 게임은 기능성을 얻기 위해 다형성을 사용한다.하위 개체를 직렬화하기 위해 엔티티 하위 유형을 저장하고 씬(scene) 저장 및 로드를 위해 하위 유형을 직렬화/직렬화하는 방법을 찾아야 했다.저장 파일에서 엔티티를 읽을 때(디시리얼라이징) 어떤 속성을 읽어야 하는지 알아야 했다.__COUNTER__, 나는 각 엔티티 클래스에 대해 고유하고 일정한 ID를 가지고 있으며, 이 ID를 사용하여 적절한 엔티티 유형으로 로딩할 수 있다.

이 접근법은 새로운 기업 유형을 일련화할 수 있도록 하기 위해 내가 추가해야 할 것은typeID = __COUNTER__;기본 ID를 덮어쓸 생성자 내에서.스프라이트의 경우:

Sprite(/* TODO: Sprite Arguments */) : Entity(/* TODO: Entity Arguments */) {
    typeID = __COUNTER__;
}

아이오스트림 과부하 개요:

friend std::ostream& operator<<(std::ostream& os, const Sprite& rhs) {
    return os << /* TODO: Outline Output */;
}
friend std::istream& operator>>(std::istream& is, Sprite& rhs) {
    return is >> /* TODO: Outline Input */;
}

이것은 당신의 수업을 위한 타입 ID를 생성하는 매우 가벼운 접근법이며, 복잡한 논리를 많이 피한다.전처리기 명령으로 그것은 꽤 기본적이지만, 그것은 몇몇 주요 가전제품에 유용한 도구를 제공한다.

참고: 카운터를 호출할 때 ID 값을 0으로 다시 시작하려면 첫 번째 ID 생성에 값을 저장하고 이후 모든 ID를 해당 값만큼 빼십시오.

읽어줘서 고마워! -YZM

TensorFlow의 매크로에는 사용법이 있다.각 TensorFlow Op는 구현으로 하나 이상의 커널을 가질 수 있다.이 낟알들은 등기소에 등록되어 있다.커널의 등록은 글로벌 변수를 정의함으로써 이루어진다 - 변수의 생성자가 등록을 할 수 있다.여기서 저자는 다음을 사용한다.__COUNTER__각 글로벌 변수에 고유한 이름을 부여한다.

#define REGISTER_KERNEL_BUILDER(kernel_builder, ...) \
  REGISTER_KERNEL_BUILDER_UNIQ_HELPER(__COUNTER__, kernel_builder, __VA_ARGS__)

#define REGISTER_KERNEL_BUILDER_UNIQ_HELPER(ctr, kernel_builder, ...) \
  REGISTER_KERNEL_BUILDER_UNIQ(ctr, kernel_builder, __VA_ARGS__)

#define REGISTER_KERNEL_BUILDER_UNIQ(ctr, kernel_builder, ...)          \
  static ::tensorflow::kernel_factory::OpKernelRegistrar                \
  registrar__body__##ctr##__object(                                 \
      SHOULD_REGISTER_OP_KERNEL(#__VA_ARGS__)                       \
      ? ::tensorflow::register_kernel::kernel_builder.Build()   \
      : nullptr,                                                \
      #__VA_ARGS__, [](::tensorflow::OpKernelConstruction* context) \
            -> ::tensorflow::OpKernel* {                \
              return new __VA_ARGS__(context);          \
            });

DEBUG 매크로 외에는 어떤 용도로도 사용해 본 적이 없다.라고 말할 수 있는 것이 편리하다.

#define WAYPOINT \
    do { if(dbg) printf("At marker: %d\n", __COUNTER__); } while(0);

ClickHouse의 메트릭스 시스템에 사용된다.

namespace CurrentMetrics
{
    #define M(NAME) extern const Metric NAME = __COUNTER__;
        APPLY_FOR_METRICS(M)
    #undef M
    constexpr Metric END = __COUNTER__;

    std::atomic<Value> values[END] {};    /// Global variable, initialized by zeros.

    const char * getDescription(Metric event)
    {
        static const char * descriptions[] =
        {
        #define M(NAME) #NAME,
            APPLY_FOR_METRICS(M)
        #undef M
        };

        return descriptions[event];
    }

    Metric end() { return END; }
}

드라이버 심 레이어에 사용했는데, 적어도 한 대의 물리적 드라이버가 활성화되었는지 확인해야 했다.

예를 들면 다음과 같다.

#if defined( USE_DRIVER1 )
#include "driver1.h"
int xxx1 = __COUNTER__;
#endif
#if defined( USE_DRIVER2 )
#include "driver2.h"
int xxx2 = __COUNTER__;
#endif
#if __COUNTER__ < 1
#error Must enable at least one driver.
#endif

나는 그것을 컴파일 시간 어설션 매크로에서 사용해 매크로가 독특하게 타이페프의 이름을 만들도록 했다.참조

만약 당신이 그 세부사항들을 원한다면.

그것은 부스트에 의해 사용된다.스택리스 코루틴을 구현하는 Asio.

헤더 파일를 참조하십시오.

결과 코루틴은 다음과 같이 보인다.

struct task : coroutine
{
  ...
  void operator()()
  {
    reenter (this)
    {
      while (... not finished ...)
      {
         ... do something ...
         yield;
         ... do some more ...
         yield;
       }
     }
   }
   ...
};

__COUNTER__런타임에 문자열을 암호화할 때 암호화 키에 대한 카운터를 어딘가에 저장하지 않고 모든 문자열에 고유 키가 있는지 확인하기 위해 Counter를 사용하면 매우 유용하다!

나는 그것을 나의 것에 사용한다.XorString런타임에 문자열을 해독하는 헤더 라이브러리 1개. 그래서 해커/크래커들이 내 이진 파일을 보려고 하면 거기서 문자열을 찾지 못하지만 프로그램이 실행되면 모든 문자열이 해독되어 정상적으로 표시된다.

#pragma once
#include <string>
#include <array>
#include <cstdarg>

#define BEGIN_NAMESPACE( x ) namespace x {
#define END_NAMESPACE }

BEGIN_NAMESPACE(XorCompileTime)

constexpr auto time = __TIME__;
constexpr auto seed = static_cast< int >(time[7]) + static_cast< int >(time[6]) * 10 + static_cast< int >(time[4]) * 60 + static_cast< int >(time[3]) * 600 + static_cast< int >(time[1]) * 3600 + static_cast< int >(time[0]) * 36000;

// 1988, Stephen Park and Keith Miller
// "Random Number Generators: Good Ones Are Hard To Find", considered as "minimal standard"
// Park-Miller 31 bit pseudo-random number generator, implemented with G. Carta's optimisation:
// with 32-bit math and without division

template < int N >
struct RandomGenerator
{
private:
    static constexpr unsigned a = 16807; // 7^5
    static constexpr unsigned m = 2147483647; // 2^31 - 1

    static constexpr unsigned s = RandomGenerator< N - 1 >::value;
    static constexpr unsigned lo = a * (s & 0xFFFF); // Multiply lower 16 bits by 16807
    static constexpr unsigned hi = a * (s >> 16); // Multiply higher 16 bits by 16807
    static constexpr unsigned lo2 = lo + ((hi & 0x7FFF) << 16); // Combine lower 15 bits of hi with lo's upper bits
    static constexpr unsigned hi2 = hi >> 15; // Discard lower 15 bits of hi
    static constexpr unsigned lo3 = lo2 + hi;

public:
    static constexpr unsigned max = m;
    static constexpr unsigned value = lo3 > m ? lo3 - m : lo3;
};

template <>
struct RandomGenerator< 0 >
{
    static constexpr unsigned value = seed;
};

template < int N, int M >
struct RandomInt
{
    static constexpr auto value = RandomGenerator< N + 1 >::value % M;
};

template < int N >
struct RandomChar
{
    static const char value = static_cast< char >(1 + RandomInt< N, 0x7F - 1 >::value);
};

template < size_t N, int K, typename Char >
struct XorString
{
private:
    const char _key;
    std::array< Char, N + 1 > _encrypted;

    constexpr Char enc(Char c) const
    {
        return c ^ _key;
    }

    Char dec(Char c) const
    {
        return c ^ _key;
    }

public:
    template < size_t... Is >
    constexpr __forceinline XorString(const Char* str, std::index_sequence< Is... >) : _key(RandomChar< K >::value), _encrypted{ enc(str[Is])... }
    {
    }

    __forceinline decltype(auto) decrypt(void)
    {
        for (size_t i = 0; i < N; ++i) {
            _encrypted[i] = dec(_encrypted[i]);
        }
        _encrypted[N] = '\0';
        return _encrypted.data();
    }
};

//--------------------------------------------------------------------------------
//-- Note: XorStr will __NOT__ work directly with functions like printf.
//         To work with them you need a wrapper function that takes a const char*
//         as parameter and passes it to printf and alike.
//
//         The Microsoft Compiler/Linker is not working correctly with variadic 
//         templates!
//  
//         Use the functions below or use std::cout (and similar)!
//--------------------------------------------------------------------------------

static auto w_printf = [](const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf_s(fmt, args);
    va_end(args);
};

static auto w_printf_s = [](const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf_s(fmt, args);
    va_end(args);
};

static auto w_sprintf = [](char* buf, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vsprintf(buf, fmt, args);
    va_end(args);
};

static auto w_sprintf_ret = [](char* buf, const char* fmt, ...) {
    int ret;
    va_list args;
    va_start(args, fmt);
    ret = vsprintf(buf, fmt, args);
    va_end(args);
    return ret;
};

static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vsprintf_s(buf, buf_size, fmt, args);
    va_end(args);
};

static auto w_sprintf_s_ret = [](char* buf, size_t buf_size, const char* fmt, ...) {
    int ret;
    va_list args;
    va_start(args, fmt);
    ret = vsprintf_s(buf, buf_size, fmt, args);
    va_end(args);
    return ret;
};

//Old functions before I found out about wrapper functions.
//#define XorStr( s ) ( XorCompileTime::XorString< sizeof(s)/sizeof(char) - 1, __COUNTER__, char >( s, std::make_index_sequence< sizeof(s)/sizeof(char) - 1>() ).decrypt() )
//#define XorStrW( s ) ( XorCompileTime::XorString< sizeof(s)/sizeof(wchar_t) - 1, __COUNTER__, wchar_t >( s, std::make_index_sequence< sizeof(s)/sizeof(wchar_t) - 1>() ).decrypt() )

//Wrapper functions to work in all functions below
#define XorStr( s ) []{ constexpr XorCompileTime::XorString< sizeof(s)/sizeof(char) - 1, __COUNTER__, char > expr( s, std::make_index_sequence< sizeof(s)/sizeof(char) - 1>() ); return expr; }().decrypt()
#define XorStrW( s ) []{ constexpr XorCompileTime::XorString< sizeof(s)/sizeof(wchar_t) - 1, __COUNTER__, wchar_t > expr( s, std::make_index_sequence< sizeof(s)/sizeof(wchar_t) - 1>() ); return expr; }().decrypt()

END_NAMESPACE

나는 사용할 작정이다__COUNTER__코드베이스의 모든 파일에 고유한 식별자를 부여하여 고유한 코드가 내장된 시스템의 ASSITE 로깅에 사용될 수 있도록 한다.

이 방법은 파일 이름을 저장하는 데 문자열을 사용하는 것보다 훨씬 더 효율적이다(사용).__FILE__), 특히 작은 ROM을 가진 임베디드 시스템.나는 이 기사를 읽으면서 그 생각을 생각했다. Embedded.com에서 자신을 주장하라.GCC 기반 컴파일러로만 작동한다는 게 아쉽다.

기능을 제대로 이해하고 있다면 Perl에서 작업할 때 기존 GUI에 이벤트 로깅 기능을 추가하면서 해당 기능을 갖고 싶었다.필요한 손 테스트(sigh)를 통해 완벽한 커버리지를 보장받고 싶었기 때문에 모든 테스트 포인트를 파일에 기록했고,__counter__가치관 덕분에 커버리지에서 빠진 것을 쉽게 볼 수 있었다.그대로, 나는 그에 상응하는 것을 손으로 코딩했다.

이 기사에서 고유한 유형을 생성하기 위해 사용했었습니다: http://www.codeproject.com/Articles/42021/Sealing-Classes-in-C

__COUNTER__다른 것과 달리 독특하다고 보장된다.__LINE__어떤 컴파일러들은 허락한다.__LINE__리셋되다#vms 파일도 재설정됨__LINE__.

우리의 코드에서 우리는 일부 제품에 대한 테스트 케이스를 추가하는 것을 잊었다.나는 지금 매크로를 몇 개 구현해서 우리는 우리가 추가하거나 제거하는 각 제품에 대한 테스트 케이스를 컴파일 시간에 가지고 있다고 주장할 수 있다.

블로그 게시물에서 이 게시물은deferC++11의 골랑 명세서

template <typename F>
struct privDefer {
    F f;
    privDefer(F f) : f(f) {}
    ~privDefer() { f(); }
};

template <typename F>
privDefer<F> defer_func(F f) {
    return privDefer<F>(f);
}

#define DEFER_1(x, y) x##y
#define DEFER_2(x, y) DEFER_1(x, y)
#define DEFER_3(x)    DEFER_2(x, __COUNTER__)
#define defer(code)   auto DEFER_3(_defer_) = defer_func([&](){code;})

그런 다음 다음을 수행할 수 있다.

int main()
{
    FILE* file = open("file.txt");
    defer(fclose(file));

    // use the file here
    // ....
}

나는 그것이 UI에 단계를 표시하는 데 유용하다는 것을 알았다.이렇게 하면 단계 라벨이 잘못 표시될 염려 없이 단계를 추가, 제거 또는 재주문하기가 정말 쉽다.

#include <iostream>

#define STR_IMPL(s)  #s
#define STR(s)  STR_IMPL(s)
#define STEP  STR(__COUNTER__) ": "

int main()
{
    std::cout 
        << STEP "foo\n"
        << STEP "bar\n"
        << STEP "qux\n"
        ;
}

출력:

0: foo
1: bar
2: qux

0이 아닌 1부터 시작하는 것은 연습으로 남는다.

참조URL: https://stackoverflow.com/questions/652815/has-anyone-ever-had-a-use-for-the-counter-pre-processor-macro

반응형