CRTP неопределенная ссылка только с GCC, -fpermissive - PullRequest
0 голосов
/ 01 июля 2018

Я добился большого успеха, используя шаблон любопытных повторяющихся шаблонов для шаблона Subject Observer в моей библиотеке. Я компилирую с помощью gcc и Visual Studio 2017. Этот код месяцами использовался на компьютерах с Windows и Linux.

Недавно я решил провести рефакторинг. Перемещение предметного наблюдателя CRTP в минимальный шаблон, затем специфичные для CUDA части в производный класс. Вот так:

SubjectObserver.hpp:

#ifndef SUBJECTOBSERVER_HPP_
#define SUBJECTOBSERVER_HPP_

template <typename T_subject, typename T_message> class Observer
{
public:

    virtual void ReceiveMessage( T_subject* subject, T_message message ) = 0;

protected:
    T_subject & subject;

    Observer( T_subject & subject )
    :
    subject( subject ){ subject.RegisterObserver( *this );  }

~Observer(){ subject.UnregisterObserver( *this ); }
};
#endif /* SUBJECTOBSERVER_HPP_ */

И CudaSubjectObserver.hpp:

#ifndef CUDASUBJECTOBSERVER_HPP_
#define CUDASUBJECTOBSERVER_HPP_

#include "SubjectObserver.hpp"

template <typename T_subject, typename T_message> class CudaObserver : public Observer<T_subject, T_message>{
public:

void ReceiveMessageBase( T_subject* subject, T_message message, cudaEvent_t message_ready ){
/*.....*/
    ReceiveMessage( subject, message );
/*.....*/
}

protected:

    CudaObserver( T_subject & subject, cudaStream_t & observer_stream )
    :
    Observer<T_subject, T_message>( subject ),
    { }

    ~CudaObserver(){ }

};
#endif /* CUDASUBJECTOBSERVER_HPP_ */

В Visual Studio 2017 это прекрасно работает. С gcc 5.4.0 я получаю «неопределенные ссылки» в CudaObserver на переменные и методы-члены Observer. Как:

../CudaSubjectObserver.hpp:78:17: error: ‘ReceiveMessage’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]

Что можно легко исправить, явно указав в CudaObserver:

Observer<T_subject, T_message>::ReceiveMessage( subject, message );

Но я бы хотел лучше понять причину этого. Очевидно, если я передам флаг -fpermissive, то неявная форма будет создана? Это плохая практика? Потому что я ценю более короткую неявную форму. Это легче читать.

...