0

I have been tasked to remove Rogue wave from our very old projects. I am creating wrappers around the main RW objects ( RWCString, RWCollectable, RWCRegEx, RWSet

I am having an issue with RWSet

Creating a POC from the Bus example that Rogue wave publishes in its documentation.

I am getting linker error on the >> operator. My wrapper is just a pass through wrapper.

I do not get the linker error on the << operator. If I take the >>operator ( restoreGuts ) out of the project, the project compiles and saves the data to a file ( RWFile ).

#pragma once

#ifndef __BUS_H__
#define __BUS_H__

#include <rw/rwset.h>
#include <rw/collstr.h>
#include <rw/collect.h>

#include <OptumBaseCollectable.h>
#include <OptumSet.h>
#include <rw/epersist.h>
#include <rw/edefs.h>

#define MODULE_FUNCTION
class Bus  : public OptumBaseCollectable {

RW_DECLARE_COLLECTABLE_CLASS(MODULE, Bus)
//RWDECLARE_COLLECTABLE(Bus)

public:

  Bus();
  Bus(int busno, const RWCString& driver);
  ~Bus();
  //OptumBaseCollectable* optBaseColl;
  // Inherited from class "RWCollectable":
  RWspace      binaryStoreSize() const;
  int          compareTo(const OptumBaseCollectable*) const;
  RWBoolean    isEqual(const OptumBaseCollectable*) const;
  unsigned     hash() const;
  void         restoreGuts(RWFile&);
  void         restoreGuts(RWvistream&);
  void         saveGuts(RWFile&) const;
  void         saveGuts(RWvostream&) const; 
 /* RWCollectable* newSpecies() const;*/

  void         addPassenger(const char* name);
  void         addCustomer(const char* name);
  size_t       customers() const;
  size_t       passengers() const;
  RWCString    driver() const     {return driver_;}
  int          number() const     {return busNumber_;}

  inline friend RWFile& operator>>(RWFile& f, OptumSet*& pCl);

  //RWvistream& operator>>(RWvistream& vstream, const Bus* p);

private:

  OptumSet *      customers_;
  OptumSet *      passengers_;
  int          busNumber_;
  RWCString    driver_;  
};

RWDECLARE_PERSISTABLE(Bus)

class Client : public RWCollectable  {
  RWDECLARE_COLLECTABLE(Client)
  Client();
  Client(const char* name);
  RWspace      binaryStoreSize() const;
  int          compareTo(const RWCollectable*) const;
  RWBoolean    isEqual(const RWCollectable*) const;
  unsigned     hash() const;
  void         restoreGuts(RWFile&);
  void         restoreGuts(RWvistream&);
  void         saveGuts(RWFile&) const;
  void         saveGuts(RWvostream&) const;
private:
  RWCString    name_;
//ignore other client information for this example
};
#endif

Bus.cpp
#include "StdAfx.h"
#include "bus.h"
#include <rw/pstream.h>
#include <rw/rwfile.h>
#include <rw/epersist.h>
#ifdef __GLOCK__
#include <fstream.hxx>
#else
#include <fstream>
#endif

RW_DEFINE_COLLECTABLE_CLASS_BY_ID(MODULE, Bus,100)

Bus::Bus() :
  busNumber_  (0),
  driver_     ("Unknown"),
  passengers_ (rwnil)
{
    //optBaseColl = new OptumBaseCollectable();
}

Bus::Bus(int busno, const RWCString& driver) :
  busNumber_  (busno),
  driver_     (driver),
  passengers_ (rwnil)
{
    customers_ = new OptumSet(64);  
}

Bus::~Bus()  {
  customers_->clearAndDestroy();
  delete passengers_;
  delete customers_;
}

RWspace
Bus::binaryStoreSize() const  {
  RWspace count = RWCollectable::binaryStoreSize() +
    customers_->recursiveStoreSize() +
    sizeof(busNumber_) +
    driver_.binaryStoreSize();

 if (passengers_)
     count += passengers_->recursiveStoreSize();
   else
     count += nilStoreSize();

   return count;
}


int
Bus::compareTo(const OptumBaseCollectable* c) const  {
  const Bus* b = (const Bus*)c;
  if (busNumber_ == b->busNumber_) return 0;
  return busNumber_ > b->busNumber_ ? 1 : -1;
}

RWBoolean
Bus::isEqual(const OptumBaseCollectable* c) const  {
  const Bus* b = (const Bus*)c;
  return busNumber_ == b->busNumber_;
}

unsigned
Bus::hash() const  {
  return (unsigned)busNumber_;
}

size_t
Bus::customers() const  {
  return customers_->entries();
}

size_t
Bus::passengers() const{    return passengers_ ? passengers_->entries() : 0;
}

void 
Bus::saveGuts(RWFile& f) const  {
  OptumBaseCollectable::saveGuts(f);    // Save base class
  f.Write(busNumber_);           // Write primitive directly
  f << driver_ << customers_;    // Use Rogue Wave provided versions
  f << passengers_;              // Will detect nil pointer automatically
}

void 
Bus::saveGuts(RWvostream& strm) const  {
  OptumBaseCollectable::saveGuts(strm);   // Save base class
  strm << busNumber_;              // Write primitives directly
  strm << driver_ << customers_;   // Use Rogue Wave 
                                   // provided versions
  strm << passengers_;     // Will detect nil pointer automatically
}

void Bus::restoreGuts(RWFile& f)  {
  OptumBaseCollectable::restoreGuts(f);  // Restore base class
  f.Read(busNumber_);             // Restore primitive
  f >> driver_ >> customers_;     // Uses Rogue Wave
                                  // provided versions

  delete passengers_;             // Delete old RWSet
  f >> passengers_;               // Replace with a new one
}

void Bus::restoreGuts(RWvistream& strm)  {
  RWCollectable::restoreGuts(strm); // Restore base class
  strm >> busNumber_ >> driver_ >> customers_;

  delete passengers_;             // Delete old RWSet
  strm >> (RWCollection&)passengers_;            // Replace with a new one
}

void
Bus::addPassenger(const char* name)  {
  Client* s = new Client(name);
  customers_->insert( s );

  if (!passengers_)
    passengers_ = new OptumSet(64);

  passengers_->insert(s);
}

void
Bus::addCustomer(const char* name)  {
  customers_->insert( new Client(name) );
}

///////////////    Here are Client methods //////////////
RWDEFINE_NAMED_COLLECTABLE(Client,"client")

Client::Client() {} // Uses RWCString default constructor

Client::Client(const char* name) : name_(name) {}

RWspace
Client::binaryStoreSize() const {
  return name_.binaryStoreSize();
}

int
Client::compareTo(const RWCollectable* c) const  {
  return name_.compareTo(((Client*)c)->name_);
}

RWBoolean
Client::isEqual(const RWCollectable* c) const  {
  return name_ == *((Client*)c)->name_;
}

unsigned
Client::hash() const  {
  return name_.hash();
}

void
Client::restoreGuts(RWFile& f)  {
  f >> name_;
}

void
Client::restoreGuts(RWvistream& vis)  {
  vis >> name_;
}

void
Client::saveGuts(RWFile& f) const  {
  f << name_;
}

void
Client::saveGuts(RWvostream& vos) const  {
  vos << name_;
}

    #ifndef _OPTUMSET_H
#define _OPTUMSET_H
#include <rw\rwset.h>

#define MODULE_FUNCTION
class __declspec(dllexport) OptumSet : public RWSet
{   
    RW_DECLARE_COLLECTABLE_CLASS(MODULE, OptumSet)
    //RWDECLARE_COLLECTABLE(OptumSet)
public:     
    OptumSet (size_t n = RWDEFAULT_CAPACITY);
    OptumSet (const OptumSet & h);
    virtual ~OptumSet();

};

#endif

OptumSet.CPP

#include <OptumSet.h>

RW_DEFINE_COLLECTABLE_CLASS_BY_ID(MODULE, OptumSet,50)
//RWDEFINE_COLLECTABLE(OptumSet, 100)

OptumSet::OptumSet(size_t n) 
{
    std::string mystr = "mystr";
}

OptumSet::~OptumSet()
{
}

OptumSet::OptumSet (const OptumSet & h) : RWSet(h)
{
    std::string mystr = "mystr";
}

Again, OptumSet is intended as a pass through class. I have tried every combination of the Declare and Defines that RW includes in their .h files.

Error 13 error LNK2019: unresolved external symbol "class RWFile & __cdecl operator>>(class RWFile &,class OptumSet * &)" (??5@YAAAVRWFile@@AAV0@AAPAVOptumSet@@@Z) referenced in function "public: virtual void __thiscall Bus::restoreGuts(class RWFile &)" (?restoreGuts@Bus@@UAEXAAVRWFile@@@Z) C:\Carol\Projects\RWCollectionPOC\Bus.obj RWCollectionPOC

I am expecting to use the documented public >> RW method of class RWFile &, Class *&). It isn't virtual so I can't override it. It is public so I am trying to just pass through to the RWCollectable which has the >> method and is the very base of RWSet.

If you are interested in the whole POC, let me know I can provide it.

Thanks in advance

This isn't a duplicate. This has to do more with the Roguewave implementation then the linker error. I know I am missing something, but I don't know what it is. If I add the declaration of >> then I will get that it is already defined. So I am pretty confused.

Donahue
  • 1
  • 3
  • Well, you declared `operator>>` taking `OptumSet*`, but never implemented it; hence linker error. You didn't declare a similar `operator<<`; I bet `RWFile` provides an overload taking `void*`, and that's what gets called. – Igor Tandetnik Oct 29 '17 at 20:02
  • Well the function has been declared and is used but you have not provided a definition for it. Pretty straight forward. – Captain Obvlious Oct 29 '17 at 20:03
  • It is a pass through. Rogue wave defines it in the Define and declare macros. Sorry I don't think I explained that well enough. The Macros expand to define and declare the methods. So.. it would create a >> method with the RWFile and the OptumSet. Plus, if what you say is true, why does the << work just fine. I don't have that declared or defined either. – Donahue Oct 29 '17 at 23:54

0 Answers0