2017-11-18 17 views
0

문제점 : 내 시스템에는 많은 통계 계산기가 클래스로 포장되어 있습니다. 제 계산은이 계산기의 값을 '합계'라는 단일 값으로 결합하는 것입니다. 이 계산기는 테이블로 주어 결합하는 방법을 설명합니다메타 프로그래밍을 사용하여 코드를 생성하는 방법은 무엇입니까?

'모델'--- CSV 파일이나 MySQL은 테이블

instance_name,accessor,argument,post_processing_function_name 
fleet_statistics,getCash,2017,func1 
city_statistics,getPopulation,2016,func2 
.... 
.... 

내 현재 솔루션 중 하나 : 나는에 파이썬 스크립트를 작성 CSV 파일을 읽고이 같은 C++ 코드를 생성 : 코드를 생성하기 위해 파이썬을 사용하여

double computeTotal() 
{ 
    double total = 0; 
    total += func1(fleet_statistics->getCash(2017)); 
    total += func2(city_statistics->getPopulation(2016)); 
    .... 
    .... 
} 

매우 편리하지만, 문제는 더 이상 '순수'C++ 프로그램입니다 없다는 것이다. 생성 된 C++ 파일이 최신인지 확인하기 위해 makefile을 해킹해야합니다.

더 우아한 해결책은 메타 프로그래밍을 사용하여 파이썬이 아닌 C++를 사용하여 C++로 코드를 생성하는 것입니다. 누구든지이 일을하는 방법을 보여줄 수 있습니까?

  1. CSV 파일로 어떤 비즈니스 로직 관련-스크립트 생성됩니다

    돌출 몇 점을 언급합니다. 그것에는 수천 개의 행이 있습니다. 수동으로 C++ 코드를 작성하는 것은 불가능합니다.

  2. 새 릴리스를 만들 때마다 CSV 파일이 바뀔 수 있습니다.

  3. 예를 들어 CSV 형식을 사용합니다. MySQL을 사용하면 테이블을 쉽게 만들 수 있습니다.

  4. instance_name 열의 객체가 반드시 동일한 BaseClass의 객체 일 필요는 없습니다. 접근 자의 함수 시그니처도 변형입니다. 따라서 함수 포인터를 사용하는 것이 편리하지 않습니다.

고마워요!

+1

입력 된 CSV 형식을 변경할 수 있습니까? – Angew

+0

@Angew 변경할 수 있습니다. 예를 들어 CSV 만 사용합니다. – user152503

+4

XY 문제와 같은 느낌입니다. 메타 프로그래밍이 정말로 필요한가요? 왜 일부 함수 포인터를 가진 C++ 데이터 구조를 정의하지 않습니까? 또는 직접 코드를 작성하지 않는 이유는 무엇입니까? 정말로 문제가 무엇인지 말하는 대신 제안 된 솔루션에 대해 질문합니다. –

답변

3

CSV 파일이 변경 될 때 C++ 코드를 생성하고 컴파일 할 필요가 없습니다. CSV 파일을 구문 분석는 C++ 객체에 C++ 함수를 호출하여 CSV 파일에 지정된 계산을 수행하면

당신이해야 할 모든 코드 ++ C 쓰기입니다.

그래서, 대략 말하면, 당신의 fleet_statisticscity_statistics 클래스는 지정된 이름을 확인하고 그 해에 대한 값을 얻기 위해 자체에 같은 이름의 해당 기능을 호출하는 double getYearValueByName(String name, int year) 기능을 가지고 몇 가지 일반적인 인터페이스를 구현해야합니다.

나는이 접근법이 단순하다는 것을 알고 있으며, 실제로는 그것보다 복잡합니다. CSV 파일을 구문 분석하고 필요에 따라 모든 기능을 갖추기 전까지는 모델을 계속 확장하여 필요에 따라 더욱 복잡하게 만들 필요가 있습니다.

+0

그러나 일반적으로 런타임에서 C++ 코드를 생성하는 것이 이치에 맞습니다. 내 대답을 보라. –

0

처음에는 CSV 파일에 수식에 대한 인터프리터를 작성하려고합니다. 당신은 아마도 정확히 그렇게하는 라이브러리를 찾을 수 있습니다. 그렇지 않으면 interpreter을 구현해야합니다 (또는 Lua 또는 Guile과 같은 기존 요소를 포함해야합니다).Dragon Book, SICP, Lisp In Small Pieces과 같은 좋은 책을 읽으십시오. AST 및 환경 (변수 바인딩 용)을 나타내야합니다. 컴파일러와 통역사에 대해 한번도 배운 적이 없다면, 이것에 대해 몇 주간 읽어야합니다 (기술은 성숙되었지만 어렵 기 때문에 모든 것을 재발 명할 수는 없습니다).

은 (난 당신이 리눅스처럼, 좋은 운영 체제가 같아요. 그렇지 않으면 내 대답을 적응) 성능이 정말 CSV 파일의 공식이 복잡하기 때문에 문제 및 계산 시간이 걸리는 경우

, 고려 JIT compilation 라이브러리 (예 : libgccjit)를 사용하여 AST (수식에서)를 일부 형식의 코드로 변환합니다. 일부 드문 경우에

(그러나 아마 귀하의 경우) 대신, 일부 임시 파일에 런타임에 일부 C++를 생성 한 후 임시 플러그인 (예를 들어, 리눅스에 dlopen & dlsym를 사용하는) 것을 plugindynamically load A와 그 컴파일 수 있습니다. C++ 컴파일러는 정말 느리기 때문에 (컴파일 타임에!) 일반적으로 이것은 노력할 가치가 없습니다. 꽤 자주 C 코드를 생성하는 것은 more appropriate (그러나 YMMV)입니다. 그러나 C 또는 C++로 컴파일하는 것은 결코 쉬운 일이 아니며 수개월의 개발 시간이 필요합니다.

생성 된 C++ 파일이 최신인지 확인하기 위해 makefile을 해킹해야합니다.

은 반드시 (큰 문제가되지이다의 Makefile를 해킹하는 데 필요한)하지 않습니다. Python 스크립트 또는 C++ 프로그램에서 g++ (또는 GCC이 아닌 경우 C++ 컴파일러)을 실행할 수 있습니다. 나는 (당신의 특정한 경우에) 그것을하는 것이 현명하다는 것을 나는 모른다.

NB. C++, 특히 메타 프로그래밍의 문맥에서 (대부분의 경우) C++ 코드 나 다른 코드를 생성하지 않지만, template metaprogramming을 참조한다는 것을 주목하십시오.

2

의견에서 입력 파일의 형식이 사용자의 제어를 받았다고 언급했습니다. 실제 메타 프로그래밍 (특히 전처리 메타 프로그래밍)을 사용하는 한 가지 방법은 파일의 형식을 X macro 패턴을 사용하기에 적합한 것으로 변경하는 것입니다. 이런 식으로 뭔가가 :

DATA_POINT(fleet_statistics,getCash,2017,func1) 
DATA_POINT(city_statistics,getPopulation,2016,func2) 

그런 다음 C++ 코드에서, 당신은이 작업을 수행 할 것 :

double computeTotal() 
{ 
    double total = 0; 
    #define DATA_POINT(instance_name,accessor,argument,post_processing_function_name) \ 
     total += post_processing_function_name(instance_name->accessor(argument)); 
    #include "datafile" 
    #undef DATA_POINT 
} 

이 방법은 컴파일되는 C++ 코드는 데이터 파일의 전처리에 의해 생성됩니다.

그러나 다른 의견 및 답변 (공유)에서 주어진 의견을 고려해야 파서가 자신의 사례에 더 적합 할 수 있습니다. 일반적으로 데이터와 코드를 분리하는 것이 좋습니다.

+0

이것은 내가 찾고있는 것입니다. 필자는 대부분의 전처리 메타 프로그래밍을 템플릿 메타 프로그래밍 (템플릿 메타 프로그래밍은 매크로를 개선하기 위해 처음 설계되었습니다)으로 변환 할 수 있음을 원격으로 상기합니다. 템플릿을 사용하여이를 구현할 수 있다고 생각하십니까? – user152503

+0

@ user152503 이유가 무엇입니까? 여기에있는 것은 본질적으로 텍스트 처리입니다. 이것은 전처리 기 (또는 다른 매크로 프로세서)가 좋은 것입니다. 템플리트는 유형 및 값 조작을위한 것입니다. – Angew

+1

@ user152503 그러나 메타 프로 그래밍이 일반 런타임 파서보다 더 적합하다는 것은 여전히 ​​확신 할 수 없습니다. "instance_name 열에있는 객체가 반드시 동일한 BaseClass에있는 것은 아닙니다." 인터페이스를 추가로 도입하지 못하게하는 요인은 무엇입니까? – Angew

1

하지만 문제는 그래서

를 C++ 더 이상 '순수'하다는 것을입니까? 그게 진짜 문제 야? 분명히 당신의 경우는 더 복잡하고 단순한 "csv 읽기 및 총계 합계"입니다. 이를 위해서는 더 복잡한 솔루션이 필요합니다. 하지만 그때 더 복잡한 필요가 없습니다.

기술에 문제가 없습니다 (예 :다른 스크립트를 통한 C++ 코드 생성). 일반적인 것이 아니지만 Google's protobuf이라는 주목할만한 사례를 통해 다른 곳에서도 볼 수 있습니다.

그래서 다른 복잡한 솔루션 (Jit 컴파일? 정말? 심지어 템플릿조차도 따라하기가 어렵습니다) 대신에 파이썬 코드 생성이 작동합니까? 그것은 잘 수행합니까? 유지하기가 쉬운가요? 리팩토링 비용은 얼마입니까? 이것들은 진짜 문제입니다.

메이크 파일은 주로 C/C++에서 사용되지만 엄격하게 제한되지는 않습니다. 실제로 하나 이상의 언어를 사용하는 모든 제작 과정을 수행 할 수 있습니다. 당신은 그들을 섞을 수 있습니다. 해킹이 아니에요. 그것은 단순히 건축 과정입니다.