protobuf can't be serialized - c++

hello eyeryone,
my protobuf version is 2.5.0, the generated header file just contains a SerializeWithCachedSizes method, I want to serialize my protobuf object to char array, and post the array by socket. in lots of tutorials refer to a method SerializeToArray method, I just need this method, but why my header file doesn't contains this method?
the first time to use protobuf, not familiar with that. if anyone can solve the problem, please show me the detail code.
proto file as:
package ddz.proto;
option optimize_for = LITE_RUNTIME;
option java_package = "ddz.proto";
option java_outer_classname = "Login";
message LoginMessage {
optional string userAccount = 1;
}
and generated header file as:
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: hello.proto
#ifndef PROTOBUF_hello_2eproto__INCLUDED
#define PROTOBUF_hello_2eproto__INCLUDED
#include <string>
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 2005000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 2005000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.
#endif
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
// ##protoc_insertion_point(includes)
namespace ddz {
namespace proto {
// Internal implementation detail -- do not call these.
void protobuf_AddDesc_hello_2eproto();
void protobuf_AssignDesc_hello_2eproto();
void protobuf_ShutdownFile_hello_2eproto();
class LoginMessage;
// ===================================================================
class LoginMessage : public ::google::protobuf::MessageLite {
public:
LoginMessage();
virtual ~LoginMessage();
LoginMessage(const LoginMessage& from);
inline LoginMessage& operator=(const LoginMessage& from) {
CopyFrom(from);
return *this;
}
static const LoginMessage& default_instance();
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
// Returns the internal default instance pointer. This function can
// return NULL thus should not be used by the user. This is intended
// for Protobuf internal code. Please use default_instance() declared
// above instead.
static inline const LoginMessage* internal_default_instance() {
return default_instance_;
}
#endif
void Swap(LoginMessage* other);
// implements Message ----------------------------------------------
LoginMessage* New() const;
void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
void CopyFrom(const LoginMessage& from);
void MergeFrom(const LoginMessage& from);
void Clear();
bool IsInitialized() const;
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
public:
::std::string GetTypeName() const;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// optional string userAccount = 1;
inline bool has_useraccount() const;
inline void clear_useraccount();
static const int kUserAccountFieldNumber = 1;
inline const ::std::string& useraccount() const;
inline void set_useraccount(const ::std::string& value);
inline void set_useraccount(const char* value);
inline void set_useraccount(const char* value, size_t size);
inline ::std::string* mutable_useraccount();
inline ::std::string* release_useraccount();
inline void set_allocated_useraccount(::std::string* useraccount);
// ##protoc_insertion_point(class_scope:ddz.proto.LoginMessage)
private:
inline void set_has_useraccount();
inline void clear_has_useraccount();
::std::string* useraccount_;
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
friend void protobuf_AddDesc_hello_2eproto_impl();
#else
friend void protobuf_AddDesc_hello_2eproto();
#endif
friend void protobuf_AssignDesc_hello_2eproto();
friend void protobuf_ShutdownFile_hello_2eproto();
void InitAsDefaultInstance();
static LoginMessage* default_instance_;
};
// ===================================================================
// ===================================================================
// LoginMessage
// optional string userAccount = 1;
inline bool LoginMessage::has_useraccount() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
inline void LoginMessage::set_has_useraccount() {
_has_bits_[0] |= 0x00000001u;
}
inline void LoginMessage::clear_has_useraccount() {
_has_bits_[0] &= ~0x00000001u;
}
inline void LoginMessage::clear_useraccount() {
if (useraccount_ != &::google::protobuf::internal::kEmptyString) {
useraccount_->clear();
}
clear_has_useraccount();
}
inline const ::std::string& LoginMessage::useraccount() const {
return *useraccount_;
}
inline void LoginMessage::set_useraccount(const ::std::string& value) {
set_has_useraccount();
if (useraccount_ == &::google::protobuf::internal::kEmptyString) {
useraccount_ = new ::std::string;
}
useraccount_->assign(value);
}
inline void LoginMessage::set_useraccount(const char* value) {
set_has_useraccount();
if (useraccount_ == &::google::protobuf::internal::kEmptyString) {
useraccount_ = new ::std::string;
}
useraccount_->assign(value);
}
inline void LoginMessage::set_useraccount(const char* value, size_t size) {
set_has_useraccount();
if (useraccount_ == &::google::protobuf::internal::kEmptyString) {
useraccount_ = new ::std::string;
}
useraccount_->assign(reinterpret_cast<const char*>(value), size);
}
inline ::std::string* LoginMessage::mutable_useraccount() {
set_has_useraccount();
if (useraccount_ == &::google::protobuf::internal::kEmptyString) {
useraccount_ = new ::std::string;
}
return useraccount_;
}
inline ::std::string* LoginMessage::release_useraccount() {
clear_has_useraccount();
if (useraccount_ == &::google::protobuf::internal::kEmptyString) {
return NULL;
} else {
::std::string* temp = useraccount_;
useraccount_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
return temp;
}
}
inline void LoginMessage::set_allocated_useraccount(::std::string* useraccount) {
if (useraccount_ != &::google::protobuf::internal::kEmptyString) {
delete useraccount_;
}
if (useraccount) {
set_has_useraccount();
useraccount_ = useraccount;
} else {
clear_has_useraccount();
useraccount_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
}
}
// ##protoc_insertion_point(namespace_scope)
} // namespace proto
} // namespace ddz
// ##protoc_insertion_point(global_scope)
#endif // PROTOBUF_hello_2eproto__INCLUDED

The method, SerializeToArray is defined as "bool SerializeToArray(void* data, int size) const;" within the message_lite.h file.
I can see that #include has been defined in your 'hello.proto' file. So you should have access to this function within your calling program.
See the example at proto file and call to Serialize method at https://stackoverflow.com/a/23945901/3685825
In past, I have pushed the serialized data across the socket. You may need to consider adding message Length before the actual message and send it across socket.
See the example at https://stackoverflow.com/a/11339251/3685825
Hope this helps!

Related

Populating a wrapper class with pass-through methods

I inherited a large rather-old C++98 codebase which is now luckily using C++17. I have an interface in a header file interfaceHeader.h as follows:
struct PluginInterface {
void (*method1)(bool enabled);
void (*method2)(int param1, int param2);
bool (*method3)(const char *path, const int& val);
};
then in another source cpp file:
MyImplementingClass *gClass = new gClass();
void method1(bool enabled) {
gClass->method1(enabled);
}
void method2(int p1, int p2) {
gClass->method2(p1, p2);
}
bool method3(const char *path, const int& val) {
return gClass->method3(path, val);
}
void pupulateInterface(PluginInterface& iface) {
iface.method1 = method1;
iface.method1 = method2;
iface.method1 = method3;
...
}
I don't have control over that global variable nor on the fact that the interface must be a struct of function pointer.
How can I reduce the boilerplate here? I tried using std::bind but it didn't work: a std::function cannot be converted to a C function pointer.
void pupulateInterface2(PluginInterface& iface) {
iface.method1 = [](bool enabled){
gClass->method1(enabled);
};
iface.method2 = [](int param1, int param2){
gClass->method2(param1,param2);
};
iface.method3 = [](const char *path, const int& val){
return gClass->method3(path, val);
};
}

Non-void methods in base class cannot access all methods in member class

I have a class TCPReceiver having as a private member an instance of a class StreamReassembler. When trying to access a method within StreamReassembler i noticed that outside of a void function i do not have access to all methods within StreamReassembler.
Implementation of StreamReassembler:
#include <cstdint>
#include <string>
#include <vector>
#include <algorithm>
class StreamReassembler {
private:
size_t _capacity;
std::vector<std::pair<std::string, size_t>> storedInMemory;
size_t lastByteWritten;
size_t segmentSize;
public:
StreamReassembler(const size_t capacity);
bool allowWritingToBuffer(const std::string &segment) const;
size_t freeMemory();
size_t getLastByteWritten();
size_t unassembled_bytes() const;
bool empty() const;
};
Source file:
#include "stream_reassembler.hh"
using namespace std;
StreamReassembler::StreamReassembler(const size_t capa)
: _output(capa), _capacity(capa), storedInMemory(0), lastByteWritten(0), segmentSize(0) {}
void StreamReassembler::push_substring(const string &data, const size_t index, const bool eof) {
segmentSize = sizeof(data);
if (index == lastByteWritten + 1) { // if current received segment is next in order
if (allowWritingToBuffer(data)) { // check if there's enough space on buffer to write segment
_output.write(data);
lastByteWritten += segmentSize; // update lastByteWritten to check next segment
}
} else {
if (segmentSize <= freeMemory()) { // make sure capacity is not exceeded
storedInMemory.emplace_back(std::make_pair(data, index));
}
}
if (segmentSize > freeMemory() or eof) {
std::sort(storedInMemory.begin(),
storedInMemory.end(),
[](std::pair<std::string, size_t> &rhs, std::pair<std::string, size_t> &lhs) {
return rhs.second > lhs.second;
});
for (const auto & segment : storedInMemory){
_output.write(segment.first);
}
lastByteWritten = index + segmentSize;
}
}
size_t StreamReassembler::unassembled_bytes() const { return storedInMemory.size() * sizeof(storedInMemory[0].first); }
bool StreamReassembler::empty() const { return storedInMemory.empty(); }
bool StreamReassembler::allowWritingToBuffer(const std::string &segment) const {
return sizeof(segment) >= _output.remaining_capacity();
}
size_t StreamReassembler::freeMemory() { return _capacity - unassembled_bytes() - _output.buffer_size(); }
size_t StreamReassembler::getLastByteWritten() {return lastByteWritten;}
The class in which i have problems accessing methods:
#include "stream_reassembler.hh"
#include <optional>
class TCPReceiver {
StreamReassembler _reassembler;
size_t _capacity;
public:
TCPReceiver(const size_t capacity) : _reassembler(capacity), _capacity(capacity) {}
std::optional<WrappingInt32> ackno() const;
size_t window_size() const;
size_t unassembled_bytes() const { return _reassembler.unassembled_bytes(); }
void segment_received(const TCPSegment &seg);
};
#include "tcp_receiver.hh"
using namespace std;
void TCPReceiver::segment_received(const TCPSegment &seg) {
_reassembler.getLastByteWritten(); //working
}
optional<WrappingInt32> TCPReceiver::ackno() const {
// last byte + 1
_reassembler.getLastByteWritten(); //not working
}
size_t TCPReceiver::window_size() const { return _capacity - _reassembler.stream_out().buffer_size(); }
Example that works fine:
void TCPReceiver::segment_received(const TCPSegment &seg) {
_reassembler.getLastByteWritten();
}
I get the following error: 'this' argument to member function 'getLastByteWritten' has type 'const StreamReassembler', but function is not marked const
optional<WrappingInt32> TCPReceiver::ackno() const {
// last byte + 1
_reassembler.getLastByteWritten();
}
You're trying to call a non-const function from a const function. Your error says so. Either your calling function needs to be non-const, or the receiving function needs to be const.
More specifically, your member variable may be mutated from the call to your const method.

Segmentation fault when run files generated by protoc

I have generated multiple classes from the protobuf files with the protcompiler. In these classes there is the redefinition of the assignment operator and when I try to make an assagnment the program returns segfault. In particular the error that returns is 0x000000000060be60 in PtrTag (this=0x7f1808001a28) at /usr/include/google/protobuf/metadata_lite.h:136 136 return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask. This function is a library function and I don't know why returns error. There is some library that I have to link in compilation time in addition to the libprotobuf or some object files?
A sample of class generated by protoc is:
class LocalizationEstimate : public ::google::protobuf::Message /* ##protoc_insertion_point(class_definition:apollo.localization.LocalizationEstimate) */ {
public:
LocalizationEstimate();
virtual ~LocalizationEstimate();
LocalizationEstimate(const LocalizationEstimate& from);
inline LocalizationEstimate& operator=(const LocalizationEstimate& from) {
CopyFrom(from);
return *this;
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _internal_metadata_.mutable_unknown_fields();
}
static const ::google::protobuf::Descriptor* descriptor();
static const LocalizationEstimate& default_instance();
static inline const LocalizationEstimate* internal_default_instance() {
return reinterpret_cast<const LocalizationEstimate*>(
&_LocalizationEstimate_default_instance_);
}
static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
1;
void Swap(LocalizationEstimate* other);
// implements Message ----------------------------------------------
inline LocalizationEstimate* New() const PROTOBUF_FINAL { return New(NULL); }
LocalizationEstimate* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void CopyFrom(const LocalizationEstimate& from);
void MergeFrom(const LocalizationEstimate& from);
void Clear() PROTOBUF_FINAL;
bool IsInitialized() const PROTOBUF_FINAL;
size_t ByteSizeLong() const PROTOBUF_FINAL;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const PROTOBUF_FINAL;
void InternalSwap(LocalizationEstimate* other);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return NULL;
}
inline void* MaybeArenaPtr() const {
return NULL;
}
public:
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// repeated .apollo.common.TrajectoryPoint trajectory_point = 5;
int trajectory_point_size() const;
void clear_trajectory_point();
static const int kTrajectoryPointFieldNumber = 5;
const ::apollo::common::TrajectoryPoint& trajectory_point(int index) const;
::apollo::common::TrajectoryPoint* mutable_trajectory_point(int index);
::apollo::common::TrajectoryPoint* add_trajectory_point();
::google::protobuf::RepeatedPtrField< ::apollo::common::TrajectoryPoint >*
mutable_trajectory_point();
const ::google::protobuf::RepeatedPtrField< ::apollo::common::TrajectoryPoint >&
trajectory_point() const;
// optional .apollo.common.Header header = 1;
bool has_header() const;
void clear_header();
static const int kHeaderFieldNumber = 1;
const ::apollo::common::Header& header() const;
::apollo::common::Header* mutable_header();
::apollo::common::Header* release_header();
void set_allocated_header(::apollo::common::Header* header);
// optional .apollo.localization.Pose pose = 2;
bool has_pose() const;
void clear_pose();
static const int kPoseFieldNumber = 2;
const ::apollo::localization::Pose& pose() const;
::apollo::localization::Pose* mutable_pose();
::apollo::localization::Pose* release_pose();
void set_allocated_pose(::apollo::localization::Pose* pose);
// optional .apollo.localization.Uncertainty uncertainty = 3;
bool has_uncertainty() const;
void clear_uncertainty();
static const int kUncertaintyFieldNumber = 3;
const ::apollo::localization::Uncertainty& uncertainty() const;
::apollo::localization::Uncertainty* mutable_uncertainty();
::apollo::localization::Uncertainty* release_uncertainty();
void set_allocated_uncertainty(::apollo::localization::Uncertainty* uncertainty);
// optional .apollo.localization.MsfStatus msf_status = 6;
bool has_msf_status() const;
void clear_msf_status();
static const int kMsfStatusFieldNumber = 6;
const ::apollo::localization::MsfStatus& msf_status() const;
::apollo::localization::MsfStatus* mutable_msf_status();
::apollo::localization::MsfStatus* release_msf_status();
void set_allocated_msf_status(::apollo::localization::MsfStatus* msf_status);
// optional .apollo.localization.MsfSensorMsgStatus sensor_status = 7;
bool has_sensor_status() const;
void clear_sensor_status();
static const int kSensorStatusFieldNumber = 7;
const ::apollo::localization::MsfSensorMsgStatus& sensor_status() const;
::apollo::localization::MsfSensorMsgStatus* mutable_sensor_status();
::apollo::localization::MsfSensorMsgStatus* release_sensor_status();
void set_allocated_sensor_status(::apollo::localization::MsfSensorMsgStatus* sensor_status);
// optional double measurement_time = 4;
bool has_measurement_time() const;
void clear_measurement_time();
static const int kMeasurementTimeFieldNumber = 4;
double measurement_time() const;
void set_measurement_time(double value);
// ##protoc_insertion_point(class_scope:apollo.localization.LocalizationEstimate)
private:
void set_has_header();
void clear_has_header();
void set_has_pose();
void clear_has_pose();
void set_has_uncertainty();
void clear_has_uncertainty();
void set_has_measurement_time();
void clear_has_measurement_time();
void set_has_msf_status();
void clear_has_msf_status();
void set_has_sensor_status();
void clear_has_sensor_status();
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
::google::protobuf::internal::HasBits<1> _has_bits_;
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::apollo::common::TrajectoryPoint > trajectory_point_;
::apollo::common::Header* header_;
::apollo::localization::Pose* pose_;
::apollo::localization::Uncertainty* uncertainty_;
::apollo::localization::MsfStatus* msf_status_;
::apollo::localization::MsfSensorMsgStatus* sensor_status_;
double measurement_time_;
friend struct protobuf_modules_2flocalization_2fproto_2flocalization_2eproto::TableStruct;
};
Follow the code of the function called in the redefinition of the assignment operator:
void LocalizationEstimate::CopyFrom(const LocalizationEstimate& from) {
// ##protoc_insertion_point(class_specific_copy_from_start:apollo.localization.LocalizationEstimate)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void LocalizationEstimate::MergeFrom(const LocalizationEstimate& from) {
// ##protoc_insertion_point(class_specific_merge_from_start:apollo.localization.LocalizationEstimate)
GOOGLE_DCHECK_NE(&from, this);
_internal_metadata_.MergeFrom(from._internal_metadata_);
::google::protobuf::uint32 cached_has_bits = 0;
(void) cached_has_bits;
trajectory_point_.MergeFrom(from.trajectory_point_);
cached_has_bits = from._has_bits_[0];
if (cached_has_bits & 63u) {
if (cached_has_bits & 0x00000001u) {
mutable_header()->::apollo::common::Header::MergeFrom(from.header());
}
if (cached_has_bits & 0x00000002u) {
mutable_pose()->::apollo::localization::Pose::MergeFrom(from.pose());
}
if (cached_has_bits & 0x00000004u) {
mutable_uncertainty()->::apollo::localization::Uncertainty::MergeFrom(from.uncertainty());
}
if (cached_has_bits & 0x00000008u) {
mutable_msf_status()->::apollo::localization::MsfStatus::MergeFrom(from.msf_status());
}
if (cached_has_bits & 0x00000010u) {
mutable_sensor_status()->::apollo::localization::MsfSensorMsgStatus::MergeFrom(from.sensor_status());
}
if (cached_has_bits & 0x00000020u) {
measurement_time_ = from.measurement_time_;
}
_has_bits_[0] |= cached_has_bits;
}
}
In my main function I made somethinghs like:
LocalizationEstimate l = localization;
where localization is a shared variable with an other process. But this assignment return segfault.

How to refactor method using template in C++

I am in need to (or better, I have the chance to) refactor some code in order to make it cleaner.
I would like to use some template, as I think this is a good candidate, in order to reduce the code duplication.
Here is my hpp
class Monetary
{
public:
Monetary();
Monetary(const rapidjson::Value& iMonetary);
virtual ~Monetary();
[...cut...]
private:
static void initMember(const rapidjson::Value& iMonetary, const char* iName, int& oMember);
static void initMember(const rapidjson::Value& iMonetary, const char* iName, std::string& oMember);
private:
int _amount;
int _decimal_place;
std::string _currency;
std::string _type;
};
And here is the implementation for the the initMember methods:
static void Monetary::initMember(const rapidjson::Value& iMonetary, const char* iName, int& oMember)
{
rapidjson::Value::ConstMemberIterator aIterator;
aIterator = iMonetary.FindMember(iName);
if ( aIterator != iMonetary.MemberEnd() &&
aIterator->value.IsNumber() )
{
oMember = iMonetary[iName].GetInt();
}
}
static void Monetary::initMember(const rapidjson::Value& iMonetary, const char* iName, std::string& oMember)
{
rapidjson::Value::ConstMemberIterator aIterator;
aIterator = iMonetary.FindMember(iName);
if ( aIterator != iMonetary.MemberEnd() &&
aIterator->value.IsNumber() )
{
oMember = iMonetary[iName].GetString();
}
}
I was thinking about writing something like
template<typename T>
void Monetary::initMember(const rapidjson::Value& iMonetary, const char* iName, T& oMember)
{
rapidjson::Value::ConstMemberIterator aIterator;
aIterator = iMonetary.FindMember(iName);
if (aIterator == iMonetary.MemberEnd())
{
return;
//throw monetaryException
}
assignFromValue(iMonetary[iName], oMember);
}
template<>
void Monetary::assignFromValue<int>(const rapidjson::Value& iValue, int& oMember)
{
if (!iValue.IsNumber())
{
return;
//throw monetaryException
}
oMember = iValue.GetInt();
}
template<>
void Monetary::assignFromValue<std::string>(const rapidjson::Value& iValue, std::string& oMember)
{
if (!iValue.IsString())
{
return;
//throw monetaryException
}
oMember = iValue.GetString();
}
Is there any clewer way to do that ?
My suggestions:
You don't need to make assignFromValue member functions. If you can implement functionality using non-member functions, you should prefer non-member functions. See How Non-Member Functions Improve Encapsulation and How Non-Member Functions Improve Encapsulation.
You don't need to make assignFromValue function templates. They can be simple overloads.
void assignFromValue(const rapidjson::Value& iValue,
int& oMember)
{
if (!iValue.IsNumber())
{
return;
//throw monetaryException
}
oMember = iValue.GetInt();
}
void assignFromValue(const rapidjson::Value& iValue,
std::string& oMember)
{
if (!iValue.IsString())
{
return;
//throw monetaryException
}
oMember = iValue.GetString();
}
I think I'd do it with a tag-dispatched converter object:
#include <string>
#include <type_traits>
#include <stdexcept>
// simulate your value class
struct Value
{
bool IsNumber() const;
bool IsString() const;
std::string getString() const;
int getInt() const;
};
// a tag type for easy tag dispatching
template<class Type> struct tag {};
// a converter object contains all rules and conversion sequences
struct ValueConverter
{
std::string operator()(tag<std::string>, const Value& v) const
{
if (not v.IsString()) throw std::invalid_argument("not a string");
return v.getString();
}
int operator()(tag<int>, const Value& v) const
{
if (not v.IsNumber()) throw std::invalid_argument("not a number");
return v.getInt();
}
};
// write the member once
template<class Target>
void initMember(const Value& iMonetary, const char* iName, Target& oMember)
{
using target_type = std::decay_t<Target>;
auto converter = ValueConverter();
oMember = converter(tag<target_type>(), iMonetary);
}

Incomplete type --> Can't Access Pointer value from my object

I'm trying to access one of my pointers within my class, however I can't seem to even get VS to acknowledge the pointer is there.
private:
ForwardTo* forward;
and here's how I grab it from the class
ForwardTo& Persons::getForwardTo() const
{
return *forward;
}
The ForwardTo type is an inherited class that typically reads:
class ForwardToTwo : public ForwardTo
{
public:
ForwardToTwo(unsigned int strategy);
virtual std::vector<std::string> forwardMessage(Persons& person, Message& message);
unsigned int getStrategy() const { return strategy;};
private:
unsigned int strategy;
};
and finally, here's how I'm trying to access the pointer
listOfPersons.at(i).getForwardTo()->forwardMessage(listOfPersons.at(i), tempMessage);
This style of access worked previously for my OTHER pointer in my class that acts exactly this same as this one.
While typing the line to access the pointer out in VS, intelliSense picks up all the functions up to getForwardTo(), and after that, the dot operator/arrow operator don't bring up any access to functions.
Thanks again for all help.
(edit, I'm aware the function fordwardMessage() function will return a vector, I was just typing in the VS until intelliSense failed to detect the accessible functions)
(edit 2, I've tried both the . operator and the -> operator, yet neither allow intelliSense to detect any functions.)
(edit 3, additional code:
Here is my Persons Class Header:
#ifndef PERSONS_HPP
#define PERSONS_HPP
#include <string>
#include <vector>
#include <list>
#include <map>
#include "Message.hpp"
#include "TypeOne.hpp"
#include "TypeTwo.hpp"
#include "TypeThree.hpp"
#include "TypeFour.hpp"
#include "TypeFive.hpp"
class ForwardTo;
class ForwardToOne;
class ForwardToTwo;
class ForwardToThree;
class Persons
{
public:
Persons();
~Persons();
void setEmailAddress(std::string email);
std::string getEmailAddress() const;
const std::vector<std::string>& getContactList() const;
void addMessageSeen(Message message);
void addMessageContent(MessageContent mc);
void addInboxMessage(Message message);
void addContact(std::string contact);
void viewContact(const std::vector<std::string>& contacts);
void bumpContact();
void setMessageTypeOne();
void setMessageTypeTwo(unsigned int type);
void setMessageTypeThree(unsigned int quality);
void setMessageTypeFour(unsigned int type, unsigned int quality);
void setMessageTypeFive();
void setForwardTypeOne(unsigned int strategy);
void setForwardTypeTwo(unsigned int strategy);
void setForwardTypeThree(unsigned int strategy);
void printPersonsObj();
std::list<Message> getInbox() const;
MessageType& getForwardWhen() const;
ForwardTo& getForwardTo() const;
private:
std::map<MessageContent, unsigned int> messageList;
std::list<Message> inbox;
std::vector<std::string> contactList;
std::string emailAddress;
ForwardTo* forward;
MessageType* forwardWhen;
};
And here is my Persons.cpp file is:
#include "Persons.hpp"
#include "ForwardToOne.hpp"
#include "ForwardToTwo.hpp"
#include "ForwardToThree.hpp"
#include <iostream>
Persons::Persons()
:emailAddress(""), contactList(), inbox(), messageList()
{
}
Persons::~Persons()
{
//delete forwardWhen;
//delete forwardTo;
}
void Persons::addMessageContent(MessageContent mc)
{
//messageSeen.insert(mc);
}
void Persons::setEmailAddress(std::string email)
{
emailAddress = email;
}
std::string Persons::getEmailAddress() const
{
return emailAddress;
}
void Persons::addContact(std::string contact)
{
contactList.push_back(contact);
}
void Persons::addInboxMessage(Message message)
{
inbox.push_back(message);
}
void Persons::viewContact(const std::vector<std::string>& contacts)
{
for(auto i = contacts.begin(); i != contacts.end(); i ++)
{
std::cout << *i << std::endl;;
}
}
void Persons::setMessageTypeOne()
{
MessageType* forwardWhen = new TypeOne();
}
void Persons::setMessageTypeTwo(unsigned int type)
{
MessageType* forwardWhen = new TypeTwo(type);
}
void Persons::setMessageTypeThree(unsigned int quality)
{
MessageType* forwardWhen = new TypeThree(quality);
}
void Persons::setMessageTypeFour(unsigned int type, unsigned int quality)
{
MessageType* forwardWhen = new TypeFour(type, quality);
}
void Persons::setMessageTypeFive()
{
MessageType* forwardWhen = new TypeFive();
}
void Persons::setForwardTypeOne(unsigned int strategy)
{
ForwardTo* forward = new ForwardToOne(strategy);
}
void Persons::setForwardTypeTwo(unsigned int strategy)
{
ForwardTo* forward = new ForwardToTwo(strategy);
}
void Persons::setForwardTypeThree(unsigned int strategy)
{
ForwardTo* forward = new ForwardToThree(strategy);
}
const std::vector<std::string>& Persons::getContactList() const
{
return contactList;
}
void Persons::bumpContact()
{
std::vector<std::string> tempList = getContactList();
std::string tempContact = tempList.at(0);
for(unsigned int i = 0; i <= tempList.size(); i ++)
{
if(i == tempList.size())
tempList.at(--i) = tempContact;
else
tempList.at(--i) = tempList.at(i);
}
}
void Persons::addMessageSeen(Message message)
{
messageList[*message.getMessageContent()] = message.getMessageContent()->getUniqueID();
}
void Persons::printPersonsObj()
{
std::cout << "PERSONS OBJECT!" << std::endl;
std::cout << "E-mail Address: " << emailAddress << std::endl;
std::cout << std::endl;
}
std::list<Message> Persons::getInbox() const
{
return inbox;
}
MessageType& Persons::getForwardWhen() const
{
return *forwardWhen;
}
ForwardTo& Persons::getForwardTo() const
{
return *forward;
}
Incomplete type normally means that at the point at which you are trying to use getForwardTo, you have not fully declared the ForwardTo class. Indeed in your persons.hop there is only a forward declaration.
Make sure you have included the header that fully declares ForwardTo in the file containing the call site.
getForwardTo() returns a T&, just use the . to access forwardMessage()