C++ polymorphic Print function not resolving properly - c++

I have created a class that abstracts a SPI flash chip library called SerialFlash by creating an abstract class of Print.h. When I try to print to this by using the ArduinoJson library, I get an error:
src/FlashMemory.cpp:99:36: error: no matching function for call to 'ArduinoJson::JsonObject::printTo(<unresolved overloaded function type>)'
root.printTo(serialFlashPrint);
^
lib/ArduinoJson/include/ArduinoJson/Internals/../Internals/JsonPrintable.hpp:34:10: note: size_t ArduinoJson::Internals::JsonPrintable<T>::printTo(Print&) const [with T = Ardu
inoJson::JsonObject; size_t = unsigned int]
size_t printTo(Print &print) const {
^
lib/ArduinoJson/include/ArduinoJson/Internals/../Internals/JsonPrintable.hpp:34:10: note: no known conversion for argument 1 from '<unresolved overloaded function type>' to
'Print&'
The file referenced in the error above is here: https://github.com/bblanchon/ArduinoJson/blob/master/include/ArduinoJson/Internals/JsonPrintable.hpp
This is the header file for the class:
#include <Arduino.h>
#include <SerialFlash.h>
#include "Print.h"
#ifndef _SerialFlashPrint_h_
#define _SerialFlashPrint_h_
class SerialFlashPrint : public Print {
public:
SerialFlashPrint(SerialFlashFile *file);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buffer, size_t size);
private:
char buf[1];
uint16_t _current_byte;
SerialFlashFile * _file;
};
#endif
And the cpp file:
#include "serialFlashPrint.h"
SerialFlashPrint::SerialFlashPrint(SerialFlashFile * file) : Print() {
this->_file = file;
this->_current_byte = 0;
}
size_t SerialFlashPrint::write(uint8_t c) {
if(_current_byte == 0){
_file->erase();
_file->seek(0);
}
sprintf(buf, "%c", c);
_file->write(buf, 1);
_current_byte++;
return 0;
}
size_t SerialFlashPrint::write(const uint8_t *buffer, size_t size){
_file->erase();
_file->seek(0);
_file->write(buffer, size);
_file->write(NULL, 1);
return 0;
};
Generally, you use print function as: the root.printTo(Serial). This code is based upon an abstraction (which I got to work previously) called Chunked output that can be seen here: https://github.com/bblanchon/ArduinoJson/wiki/Bag-of-Tricks
Does anyone have any clues for me to figure out why I am getting <unresolved overloaded function type> instead of Print&?

<unresolved overloaded function type> means that the compiler found a function with several overloads and doesn't know which one to use.
You most likely have several serialFlashPrint() in your code or libraries.
If not, then you may have triggered the Most vexing parse:
SerialFlashPrint serialFlashPrint; // <- creates an instance of SerialFlashPrint
SerialFlashPrint serialFlashPrint(); // <- declares a function returning a SerialFlashPrint

Related

Declaring an overloaded function in global namespace as friend of template class

My issue is simple. I am able to declare an overloaded function in the global namespace as a friend of a template class in a nested namespace using fundamental types, however if I change the definition and declaration of the function to return size_t, I get C2510 and C4430 errors. This only occurs with the return type of the function. size_t in the parameter list does not generate the issue. I have tried ::size_t, ::std::size_t, and std::size_t as well. Nothing seems to work. What is going on here and why?
I am using MS Visual Studio 2015
Thanks
UPDATED: Per comments I have included remaining code TestingApp.cpp. I also included stddef which does not solve the problem. With respect to the specific error messages I received, they are:
C2510 'size_t': left of '::' must be a class/struct/union TestingApp
pointer.h 41
C4430 missing type specifier - int assumed. Note: C++ does not support
default-int TestingApp pointer.h 41
Line 41 that does NOT generate compilation errors:
friend int ::fwrite<DATA_TYPE>(const Pointer<DATA_TYPE>& ptr, size_t count, FILE* stream);
Line 41 that DOES generate compilation errors:
friend size_t ::fwrite<DATA_TYPE>(const Pointer<DATA_TYPE>& ptr, size_t count, FILE* stream);
The following two files compile and run with no problem. However if I substitute int with size_t for the return type (and ONLY the return type keeping size_t as the second parameter of the function in either case) in the forward declaration, friend declaration, and definition, I get the errors indicated above.
/*******Begin Pointer.h******/
#pragma once
#include <cstdio>
namespace FW{
namespace Memory {
template <typename DATA_TYPE> class Pointer;
}
}
template <typename DATA_TYPE> inline
/* int works, size_t does not work */
int
/* size_t */
fwrite(const
FW::Memory::Pointer<DATA_TYPE>& ptr, size_t count, FILE* stream);
namespace FW{
namespace Memory{
template <typename DATA_TYPE> class Pointer {
/*Line 41*/ friend
/* int works, size_t does not work */
int
/* size_t */
::fwrite<DATA_TYPE>(const Pointer<DATA_TYPE>& ptr, size_t count, FILE* stream);
public:
/* Omitted for brevity */
private:
DATA_TYPE* m_pCurrent;
};
}
}
template <typename DATA_TYPE>
/* int works, size_t does not work */
int
/* size_t */
fwrite<DATA_TYPE>(const FW::Memory::Pointer<DATA_TYPE>& ptr, size_t count, FILE* stream) {
return fwrite(ptr.m_pCurrent, sizeof(DATA_TYPE), count, stream);
}
/*******End Pointer.h*******/
/*******Begin TestingApp.cpp******/
// TestingApp.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <cstdio>
#include <cstddef>
#include "..\DB\Pointer.h"
int main()
{
unsigned long* pData = new unsigned long[100];
for (size_t i = 0; i < 100; i++) {
pData[i] = i;
}
FW::Memory::Pointer<unsigned long> ptr(pData);
FILE* pFile = fopen("testFile", "wb");
if (pFile) {
fwrite(ptr, 10, pFile);
fclose(pFile);
}
delete[] pData;
pData = 0;
return 0;
}
/*****End TestingApp.cpp*****/

No matching function call call to constructor in header file

I have seen similar questions asked and tried their solutions but the answers to them do not seem to work. I have the following code:
.h
#include <iostream>
#include <vector>
#include <string>
using std::string; using std::vector;
struct DialogueNode;
struct DialogueOption {
string text;
DialogueNode *next_node;
int return_code;
DialogueOption(string t, int rc, DialogueNode * nn) : text{t},
return_code{rc}, next_node{nn} {}
};
struct DialogueNode {
string text;
vector <DialogueOption> dialogue_options;
DialogueNode();
DialogueNode(const string &);
};
struct DialogueTree {
DialogueTree() {}
void init();
void destroyTree();
int performDialogue();
private:
vector <DialogueNode*> dialogue_nodes;
};
.cpp
#include "dialogue_tree.h"
DialogueNode::DialogueNode(const string &t) : text{t} {}
void DialogueTree::init() {
string s = "Hello";
for(int i = 0; i < 5; i++) {
DialogueNode *node = new DialogueNode(s);
dialogue_nodes.push_back(node);
delete node;
}
}
void DialogueTree::destroyTree() {
}
int DialogueTree::performDialogue() {
return 0;
}
int main() {
return 0;
}
I get the error: error: no matching function for call to ‘DialogueNode:: DialogueNode(std::__cxx11::string&)’ DialogueNode *node = new DialogueNode(s);
EDIT additional notes on error
dialogue_tree.h:17:8: note: candidate: DialogueNode::DialogueNode()
dialogue_tree.h:17:8: note: candidate expects 0 arguments, 1 provided
dialogue_tree.h:17:8: note: candidate: DialogueNode::DialogueNode(const DialogueNode&)
dialogue_tree.h:17:8: note: no known conversion for argument 1 from ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ to ‘const DialogueNode&’
dialogue_tree.h:17:8: note: candidate: DialogueNode::DialogueNode(DialogueNode&&)
dialogue_tree.h:17:8: note: no known conversion for argument 1 from ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ to ‘DialogueNode&&’
Which makes no sense to me because I have the constructor defined to take a string as an argument.
You've declared your constructor as:
DialogueNode(const string);
But defined it as:
DialogueNode(const string &t);
Those two aren't the same; the former takes a const string while the latter takes a const string reference. You'll have to add the & to specify a reference argument:
DialogueNode(const string &);
it is because in the constructor you are specifying that the parameter will be a string of constant type and when creating an object you are passing a string. The type mismatch is the problem, either fix the constructor parameter to string or change when you are creating an object.

Pass pointer to function works in simple case but not after "class"-ifying

I am a somewhat rusty programmer, and new to C++. I've been asked to write a program that can pass a pointer to a function into another function and execute. I can make the simple case work, where everything is in a .cpp file. But when I place the code in a class inside a .h file it won't compile. I am either code blind or missing something.
Here is the code that works:
/*
* funcptr.cpp
*
* Example:
* - pass function pointer as argument
* - execute passed function
*/
#include <stdio.h>
void takes_a_function(void (*f)(void *data), void *data);
void print_char(void *data);
void print_int(void *data);
// This function gets passed (to takes_a_function)
void print_char(void *data) {
char *ch = (char *)data;
printf("%c\n", *ch);
}
// This function gets passed (to takes_a_function)
void print_int(void *data) {
int *i = (int *)data;
printf("%d\n", *i);
}
void takes_a_function(void (*f)(void *), void *data) {
//f(data); // this also works
(*f)(data);
}
int main() {
int i = 100;
takes_a_function(print_int, &i);
char ch = 'A';
takes_a_function(print_char, &ch);
}
It compiles and runs:
# g++ funcptr.cpp -o funcptr
# ./funcptr
100
A
So far so good. But then I put the code into a .h file and "class"-ify it so I can use it from anywhere, and everything falls apart:
#ifndef __funcptr_h__
#define __funcptr_h__
#include <stdio.h>
void takes_a_function(void (*f)(void *data), void *data);
void print_char(void *data);
void print_int(void *data);
void testit();
class FunctionPtr
{
public:
// This function gets passed (to takes_a_function)
void print_char(void *data) {
char *ch = (char *)data;
printf("%c\n", *ch);
}
// This function gets passed (to takes_a_function)
void print_int(void *data) {
int *i = (int *)data;
printf("%d\n", *i);
}
void takes_a_function(void (*f)(void *a), void *data) {
//f(data); // this also works
(*f)(data);
}
void testit() {
int i = 100;
takes_a_function(print_int, &i);
char ch = 'A';
takes_a_function(print_char, &ch);
}
};
#endif
The compiler error is:
# g++ funcptr.h
funcptr.h: In member function ‘void FunctionPtr::testit()’:
funcptr.h:34:33: error: invalid use of non-static member function ‘void FunctionPtr::print_int(void*)’
takes_a_function(print_int, &i);
^
funcptr.h:22:7: note: declared here
void print_int(void *data) {
^~~~~~~~~
funcptr.h:37:35: error: invalid use of non-static member function ‘void FunctionPtr::print_char(void*)’
takes_a_function(print_char, &ch);
^
funcptr.h:16:7: note: declared here
void print_char(void *data) {
^~~~~~~~~~
I've been playing with this for a while and done a fair amount of reading on passing function pointers, including on StackOverflow, however all the examples I see are simple and of no help.
Any insights are much appreciated.
Thanks to all.
It looks to me like your problem is when you call takes_a_function with your arguments.
You declared the data parameter as a pointer to a void type, not a reference to a void type.
You could try something like:
void testIt() {
int i = 100;
int * j = &i;
takes_a_function(print_int, j);
char c = 'a';
char * d = &c;
takes_a_function(print_char, d);
};
References and pointers are not exactly the same thing.
Also it looks like you forgot a #endif after you define __funtptr_h__
I hope this helped

skipping adding constructors when inheriting from std::string class

Tried to argument the std::string so that it supports method "bool operator==(int)". I got errors:
$ g++ -std=c++11 te2.cc
te2.cc: In function ‘int main(int, char**)’:
te2.cc:20:20: error: no matching function for call to ‘mstring::mstring(const char [4])’
te2.cc:20:20: note: candidates are:
te2.cc:10:7: note: mstring::mstring()
te2.cc:10:7: note: candidate expects 0 arguments, 1 provided
te2.cc:10:7: note: mstring::mstring(const mstring&)
te2.cc:10:7: note: no known conversion for argument 1 from ‘const char [4]’ to ‘const mstring&’
te2.cc:10:7: note: mstring::mstring(mstring&&)
te2.cc:10:7: note: no known conversion for argument 1 from ‘const char [4]’ to ‘mstring&&’
Here is the simple source:
#include <unordered_map>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
class mstring : public string {
public:
//mstring (char* p) : std::string(p) {};
bool operator == (int x) {
int n = atoi(this->c_str());
return (n == x);
}
};
int main(int argc, char *argv[])
{
mstring t("123");
if (t == atoi(argv[1])) {
printf("yes\n");
} else {
printf("no\n");
}
}
If I uncomment the constructor /mstring (char* p) : std::string(p) {};, then it compiles and runs fine.
The question is, if it possible to make it work without defining the constructors for mstring, just use the whatever the constructors of the base class (there is no new data member anyway)? Thanks.
What about providing a free standing operator function instead of inheriting from std::string (which makes that code more usable overall):
bool operator==(const std::string& s, int i) {
int n = atoi(s.c_str());
return (n == i);
}
bool operator==(int i, const std::string& s) {
return s == i;
}
Or even more generic:
template<typename T>
bool operator==(const std::string& s, T t) {
std::istringstream iss;
iss << t;
return (s == iss.str());
}
Classes from the std namespace aren't intended to be inherited, but just used in interfaces and function parameters. Inheriting from those classes makes your code less usable, since clients need to use your implementation instead of just using the std type.
Also note: For your particular use case it's not necessary to convert anything at all, unless you want to assert that argv[1] contains a number (where atoi() certainly isn't the best method to do so, look up stoi() instead). You can just compare the strings:
if (std::string("123") == argv[1]) {
printf("yes\n");
} else {
printf("no\n");
}
you can explicitly inherit the constructors by adding
using string::string;
in your class

Getting compile errors with Copliens 1994 counted pointer example code

OK, I am reading Copliens C++ Idioms book, and trying to run the handle/body examples in the book. After typing in the code, I am getting compile errors:
Here is the code the String and StringRep classes.
#ifndef _STRINGREP_H_
#define _STRINGREP_H_
#include <stdio.h>
#include <string.h>
class String;
class StringRep {
friend class String;
public:
StringRep() {*(rep = new char[1])='\0';}
StringRep(const StringRep& s) {
::strcpy(rep=new char[::strlen(s.rep)+1], s.rep);
}
~StringRep() { delete [] rep;}
StringRep(const char* s) {
::strcpy(rep=new char[::strlen(s)+1], s);
}
String operator+(const String& s) const {
char *buf = new char[s->length() + length() + 1];
::strcpy(buf, rep);
::strcat (buf, s->rep);
String retval(&buf);
return retval;
}
int length() const { return ::strlen(rep); }
void print() const {::printf("%s\n", rep); }
private:
StringRep(char ** const r) {
rep = *r;
*r = 0;
count = 1;
};
char *rep;
int count;
};
#endif
#ifndef _STRING_H_
#define _STRING_H_
#include <stdio.h>
#include <string.h>
#include "StringRep.h"
class String {
friend class StringRep;
public:
String operator+(const String& s) const {return *p + s;}
StringRep* operator->() const {return p;}
String() {
(p = new StringRep())->count = 1;
}
String (const String &s) { (p=s.p)->count++;}
String(const char* s) {
(p = new StringRep(s))->count = 1;
}
String operator=(const String& s) {
if (--p->count <=0) delete p;
(p = s.p)->count++;
return *this;
}
~String() { if (--p->count <= 0) delete p;; }
private:
String(char **r) {
p = new StringRep(r);
}
StringRep *p;
};
#endif
And a main.cc
#include <stdio.h>
#include <string.h>
#include "StringRep.h"
#include "String.h"
int main() {
String a("abcd"), b("efgh");
printf("a is "); a->print();
printf("b is "); b->print();
printf("concat of a+b is "); (a+b)->print();
return 0;
}
Compile errors;
GNU C++ version 4.1.2 20080704 (Red Hat 4.1.2-44) (x86_64-redhat-linux)
compiled by GNU C version 4.1.2 20080704 (Red Hat 4.1.2-44).
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 2d02d8750f9b337bb19a7dd5b4e2167e
StringRep.h: In member function 'String StringRep::operator+(const String&) const':
StringRep.h:21: error: return type 'struct String' is incomplete
StringRep.h:22: error: base operand of '->' has non-pointer type 'const String'
StringRep.h:24: error: base operand of '->' has non-pointer type 'const String'
StringRep.h:25: error: variable 'String retval' has initializer but incomplete type
String.h: In member function 'String String::operator+(const String&) const':
String.h:13: error: conversion from 'void' to non-scalar type 'String' requested
I figure that I cannot use String class until it is completely defines. Changing the
signature of the function to
String& operator+(const String& s) const {...
solves the first error, but causes the same error to show up where I am creating a
new String object
String retval(&buf);
I realize that the book I have is the 1994 reprint that I picked up. So can someone either point me newer code (if C++ coding style has changed) or point out how to fix this?
Thanks
You got a circular reference since StringRep needs to know the full definition of String to construct it in operator+. I advice to not put everything in header files, but just the declarations of the member functions and put the definitions in the .cpp (or .cc) file. That should fix it. That is also how code should be split if the class itself and / or the functions are not a template.
You need to pull the definition and declaration of everything apart. If you really want to put them in the header file, you can do so as follows:
<forward declarations, required includes>
<class itself, no functions defined>
<includes for forward declarations that are needed for function bodies>
<function bodies>
That will always work.
You can't include the String header file in the StringRep header file when you also include the StringRep header file in the String header file. This causes a circular inclusion and will prevent your code from compiling.
Think of it as:
StringRep.h loads String.h
which loads StringRep.h
which loads String.h
which loads StringRep.h
which loads ...
You can avoid this by moving the function declarations into the .cpp files and simply forward declaring the String class inside of StringRep.h (which you already do!). It won't actually try and resolve the reference to the String class until it actually compiles the code, by which time the circular inclusion issue will have been avoided.