2017-11-08 12 views
2

템플릿에 문제가 발생했습니다. & 상속. 문제가되는 코드를 여기 게시 할 수있는 코드로 썼습니다. 다음과 같이 내 코드는 다음과 같습니다템플릿 상속 : 기호를 찾을 수 없음

///////////////////////////// My header.h file 
#include <vector> 

template <class T> 
class Slider { 
protected: 
    std::vector<T> out; 
public: 
    Slider() : out() {} 
    virtual void save_result(); 
}; 

template <class T> 
class SlidingVar : public Slider<T> { 
public: 
    SlidingVar() {} 
    void save_result() {} 
}; 

template <class T> 
void slide(std::vector<T> x, Slider<T> s) {} 

///////////////////////////// My sliding_sd.cpp file 
#include <vector> 
#include "headers.h" 

void sliding_var_window(std::vector<double> x) { 
    SlidingVar<double> s; 
    slide(x, s); 
} 

위 비록 모든 "순수 C++를"코드가, 내 sliding_var_window 기능 R.에서 호출 수를 내보낼에 대한 R 패키지의 맥락에서이 일을 해요

위의 코드는 정상적으로 컴파일되지만, dlopen을 사용하여 R을로드하면 save_result() 함수에 대해 Symbol not found 오류가 발생합니다. 이상하게도, 내가 이것을 없애기 전에, 다른 유사한 기능들이 잘 작동했지만,이 기능은 작동하지 않았습니다. 다음은 빌드 순서입니다 :이 정말 R 또는 Rcpp과 아무 상관이 의심

==> R CMD INSTALL --preclean --no-multiarch --with-keep.source tsevents 

* installing to library ‘/Users/kwilliams/R/library/3.4’ 
* installing *source* package ‘TSEvents’ ... 
** libs 
clang++ -std=gnu++11 -I/usr/local/Cellar/r/3.4.2/lib/R/include -DNDEBUG -I"/Users/kwilliams/R/library/3.4/Rcpp/include" -I/usr/local/opt/gettext/include -I/usr/local/opt/readline/include -I/usr/local/include -fPIC -g -O2 -c sliding_sd.cpp -o sliding_sd.o 
clang++ -std=gnu++11 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/usr/local/opt/gettext/lib -L/usr/local/opt/readline/lib -L/usr/local/lib -L/usr/local/Cellar/r/3.4.2/lib/R/lib -L/usr/local/opt/gettext/lib -L/usr/local/opt/readline/lib -L/usr/local/lib -o TSEvents.so sliding_sd.o -L/usr/local/Cellar/r/3.4.2/lib/R/lib -lR -lintl -Wl,-framework -Wl,CoreFoundation 
installing to /Users/kwilliams/R/library/3.4/TSEvents/libs 
** R 
** preparing package for lazy loading 
** help 
*** installing help indices 
** building package indices 
** testing if installed package can be loaded 
Error: package or namespace load failed for ‘TSEvents’ in dyn.load(file, DLLpath = DLLpath, ...): 
unable to load shared object '/Users/kwilliams/R/library/3.4/TSEvents/libs/TSEvents.so': 
    dlopen(/Users/kwilliams/R/library/3.4/TSEvents/libs/TSEvents.so, 6): Symbol not found: __ZN6SliderIdE11save_resultEv 
    Referenced from: /Users/kwilliams/R/library/3.4/TSEvents/libs/TSEvents.so 
    Expected in: flat namespace 
in /Users/kwilliams/R/library/3.4/TSEvents/libs/TSEvents.so 
Error: loading failed 

하지만 누군가가 순수 C++ 툴 체인에서이 문제를 설명 할 수있는 방법을 제안 할 수 있다면, 그래서 그 것을, 내 빌드 환경을 제공하는 것 가장 환영받을 것입니다.

내가 이해하지 못하는 또 다른 재미있는 이야기 - 내가 오브젝트 파일에 정의 된 기호를 볼 때이의 save_result() 함수는 unsigned short 반환 유형이 보인다, 내가 그것을 선언 할 때 void 할 수 있습니다 :

% nm src/TSEvents.so | c++filt | grep result 
0000000000002df0 unsigned short SlidingVar<double>::save_result() 
       U Slider<double>::save_result() 

그게 정상인가요?

sliding_sd.cpp:(.rdata$_ZTV6SliderIdE[__ZTV6SliderIdE]+0x8): undefined reference to `Slider<double>::save_result()' 

Slider<double>의 VTABLE의 가상 메소드 Slider<double>::save_result() 참조 (가상 메소드 테이블)이 존재 의미

+0

실제 '최소한으로 재현 가능한 예'로 만들 수 있습니까? –

+0

@DirkEddelbuettel Fabian이 나에게 보여 줬던 방법을 설명 할 수 있습니다 - 관련없는 R/Rcpp 섹션을 제거하거나 마지막에 reprex를 추가하는 것이 더 좋습니다? –

+0

당신의'nm '에'U'가 쓰여있다 ... | C++ filt' 결과는 이미''man nm'을 볼 때 이미 흡연 총이었습니다. –

답변

1

I는 int main() { } 추가 및 추가 옵션없이 g++ 컴파일 후에 링커 오류를 재현 할 수 링크 중에는 해결할 수 없습니다. 그 원인은 save_result()template <class T> class Slider에 신고했지만 정의하지 않았기 때문입니다 (최소한 게시 한 코드에서는). 비록 Slider<double>::save_result()이 당신의 예제에서 사용 된 적이 없다면, 정의되어야합니다 (적어도 평범한 C++을 사용할 때는 적어도 R에 대해 알지 못합니다). virtual입니다. 그렇지 않으면 연결 중에 Slider<double>의 vtable을 만들 수 없습니다.

(적어도 내 재생시)

template <class T> 
class Slider { 
    /* ... */ 
    virtual void save_result() { } 
}; 

링킹 에러가 사라질 때 변경.

+0

감사합니다. 나는 이것을 시도 할 것이다. 내 의도는 이것을 오버라이드해야하는 가상 메소드로 선언하는 것이고, 또 다른 합리적인 대안은'= 0; –

+1

또한'= 0;'을 생각해 보았습니다. 그러나 이것은'slider '형의 인수를 가지고 있기 때문에'Slider ''컴파일러 오류가 발생했습니다.'Slider '에는 순수한 ('= 0') 가상 멤버 함수가 있습니다. 그러나 인수로 참조를 전달하면, 즉 템플릿'void void slide (std :: vector x, 슬라이더 ) {}'을 사용하면'= 0;'을 사용할 수 있습니다. – Fabian

+0

실제로 작동합니다. 배울 점이 많이 있습니다 ... –