컴파일 타임에 메소드가 정확히 한 곳에서 호출되는지 확인할 수 있는지 궁금합니다.
함수가 두 번 이상 (예 : 루프에서) 호출되면 괜찮지 만 두 개의 개별 루프에서 호출해서는 안됩니다.
이것은 두 부분으로 나눌 수 있습니다, 나는 또한 중 일부를 커버 솔루션에 관심이 있어요 :
(A) 방법을 확인이 적어도 하나 개의 장소에 호출
에 호출 (b)의 방법을 위해 가장 한 곳에서
코드 구조를 완전히 제어 할 수 있으며 동일한 아이디어를 얻는 다른 관용구도 환영합니다.
// class.h
class MyClass {
public:
void my_method();
}
다음은 컴파일해서는 안됩니다 (전화하지 마십시오)
#include "class.h"
int main() {
MyClass my_class;
}
다음은 컴파일하지 않아야합니다 (여러 곳에서 호출)
#include "class.h"
int main() {
MyClass my_class;
my_class.my_method();
while(true) {
my_class.my_method();
}
}
다음은 컴파일해야합니다 (정확히 한 곳에서 호출).
#include "class.h"
int main() {
MyClass my_class;
while(true) {
my_class.my_method();
}
}
답변
낮은 기술 접근 방식 :
코드 구조 (빌드 시스템 포함)를 제어 할 수 있기 때문에 여기 저 기술 솔루션이 있습니다.
- 함수 이름을 충분히 고유하게 만드십시오
- 코드에서 함수 이름을 grep하십시오. 선언과 정의가 같은 위치에 있다고 가정하면 두 번 예상됩니다.
- 헤더에 한 번
- 단일 통화 사이트에서 한 번
또는
정말로 정말로 C ++로 해결하고 싶다면 시도해보십시오.
- 컴파일 타임 카운터를 사용하여 컴파일 단위 내의 사용 횟수를 파악하십시오.
- 헤더가 여러 컴파일 단위에 포함 된 경우 함수가 ODR을 위반하는지 확인하십시오.
그러나 컴파일 타임 카운터는 검은 마술입니다 (예 : I 및 TMP를 정말로 좋아합니다).이 목적으로 ODR 위반을 강제하는 것은 비슷한 부두처럼 보입니다 (적어도 연결에 실패한 테스트 사례가 필요합니다).
그러나 진지하게 :
이러지 마 무엇을하든 래퍼 함수를 사용하면 거의 노력하지 않고 왜곡 할 수 있습니다.
auto call_my_method(MyClass& o)
{
return o.my_method();
}
MyClass::my_method()
랩퍼에서만 호출됩니다. 다른 사람들은 컴파일러에 의해 인라인 된 래퍼를 호출합니다.
다른 사람들이 제안한 바와 같이 : 당신이하려는 일을 설명한다면 훨씬 도움이 될 수 있습니다.
답변
다음은 작동 할 수있는 대략적인 아이디어입니다 (댓글이 너무 길지만 좋은 SO 답변에는 불완전합니다).
템플릿 인스턴스화 수를 계산 / 확인하여이를 달성 할 수 있습니다.
템플릿은 사용시 에만 인스턴스화됩니다 .
마찬가지로 템플릿 메소드 / 함수 본문은 호출되지 않은 경우 구문 분석 또는 컴파일 또는 링크되지 않습니다 (유효한 구문 보장 이외). 이것은 그들의 몸 안에서 어떤 인스턴스도 만들어지지 않았다는 것을 의미합니다).
전역 인스턴스화 횟수와 정적 어설 션을 유지하는 템플릿 (또는 과거 인스턴스화를 확인하는 다른 TMP 메커니즘)을 유지 관리하는 템플릿을 만들 수 있습니다.
답변
C 전처리 기와 GNU 인라인 어셈블리를 사용하여이 질문에 대한 부분적인 해결책이 있습니다.
헤더 파일 a.h
:
struct A {
// Do not call this method directly, use the macro below to call it
int _method_vUcaJB5NKSD3upQ(int i, int j);
};
// Use inline assembly to ensure that this macro is used at most once
#define method_vUcaJB5NKSD3upQ(args...) \
_method_vUcaJB5NKSD3upQ(args); \
asm (".global once_vUcaJB5NKSD3upQ; once_vUcaJB5NKSD3upQ:");
구현 파일 a.cc
:
#include <iostream>
#include "a.h"
int A::_method_vUcaJB5NKSD3upQ(int i, int j) { return i+j+5; }
// Ensure that the macro is used at least once
extern "C" const char once_vUcaJB5NKSD3upQ;
static const char get_vUcaJB5NKSD3upQ = once_vUcaJB5NKSD3upQ;
int main() {
A a;
for(int i=0; i<7; i++) {
// Use a separate statement to call the method
// (terminated by a semicolon, it cannot be a sub-expression)
auto x = a.method_vUcaJB5NKSD3upQ(2, 3);
std::cout << x << std::endl;
}
return 0;
}
이 솔루션은 프로그램이 래퍼 매크로를 사용하지 않고 밑줄로 시작하는 메소드를 직접 호출하는 것을 막지 않는다는 점에서 부분적입니다.