0

I've had good success using the Curiously Recurring Template Pattern for the Subject Observer pattern in my library. I compile with gcc and Visual Studio 2017. This code has been used for months on both Windows and Linux machines.

Recently, I decided to refactor. Moving the CRTP Subject Observer to a minimal template, then the CUDA-specific parts to a derived class. Like so:

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_ */

And 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_ */

With Visual Studio 2017, this builds fine. With gcc 5.4.0, I get "undefined references" in CudaObserver to Observer member variables and methods. Like:

../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]

Which can be fixed easily enough by explicitly specifying within CudaObserver:

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

But I would like to understand better the cause for this. Apparently if I pass the -fpermissive flag the implicit form would build? Is this bad practice? Because I do appreciate the shorter implicit form. It's easier to read.

Tyson Hilmer
  • 741
  • 7
  • 25
  • 1
    The most likely reason is a buggy compiler. After fixing the obvious syntax errors, gcc 8.1.1 has no problem with the declaration, by default. It is true that certain things have to be more explicit, when templates are involved, but I can't really find anything wrong with this simple example (I would use `this->`, though). – Sam Varshavchik Jul 01 '18 at 13:30
  • @Sam indeed `this->` works well, whereas the explicit form I gave above results in undefined references at runtime (shared library). Probably time to update my Linux build environment. – Tyson Hilmer Jul 01 '18 at 13:45
  • 2
    The shown error message in your question is not an undefined reference at runtime, it is a compilation error. You will find that accurately, and precisely, describing your question increases the odds of getting a useful answer on stackoverflow.com – Sam Varshavchik Jul 01 '18 at 14:00
  • @Sam. At compile time, I got undefined reference using the implicit form. Adding `Observer::` allowed it to build a shared library (Matlab mex). The shared library then gave undefined reference at runtime. So both actually. Whereas your helpful answer to use `this->` rather than `Observer::` allowed the shared library to run. Thank you :) – Tyson Hilmer Jul 01 '18 at 14:23
  • [It's a bug in MSVC](https://stackoverflow.com/questions/16471161/is-this-a-bug-in-gcc?rq=1) [more](https://stackoverflow.com/a/16471171/4486071) – Tyson Hilmer Jul 01 '18 at 14:34

0 Answers0