This question already has answers here:
How to have two functions that call each other C++
(2 answers)
Closed 1 year ago.
#include <iostream>
#include <stdio.h>
using namespace std;
void funB(int n){
if (n>1){
cout<<n<<" ";
funA(n/2);
}
}
void funA(int m)
{
if (m>0){
cout<<m<<" ";
funB(m-1);
}
}
int main()
{
funA(20);
return 0;
}
For this code I am getting the following error:
prog.cpp: In function ‘void funB(int)’:
prog.cpp:8:13: error: ‘funA’ was not declared in this scope
funA(n/2);
^
For this simple indirect recursion example, What is the possible error?
I even tried changing the order of the functions.
Try this. What I have done is, I have just declared the funA before the definition of both functions just so that the compiler knows that there exists a function 'funA' which is being referred to. This is called forward declaration.
#include <iostream>
#include <stdio.h>
using namespace std;
void funA(int);
void funB(int n){
if (n>1){
cout<<n<<" ";
funA(n/2);
}
}
void funA(int m)
{
if (m>0){
cout<<m<<" ";
funB(m-1);
}
}
int main()
{
funA(20);
return 0;
}
Related
In one of my project I managed to fix a bug switching from a std::vector of objects to a std::vector of pointers to the object. Using the debugger I found that the error occurred when I was calling the std::vector<T,Allocator>::clear that it is supposed to destroy the objects stored in the vector. I am happy I solved the issue but I would like to know why I was able to!
Here I attach the code incriminated:
#include <vector>
#include <memory>
#include <string>
class Base
{
public:
Base(int a);
Base(const Base& o)=default;
Base& operator=(const Base& o)=default;
Base(Base&& o)=default;
Base& operator=(Base&& o)=default;
virtual ~Base()=default;
virtual void Do();
};
class Derived: public Base
{
private:
std::string b;
public:
Derived(int a, std::string& b) : Base(a), b(b) {}
};
//Other derived classes from Base overriding Do
class Main{
private:
std::vector<Derived> v;
public:
Main();
void Do(int i, std::string& b){
/*
if something happens
v.emplace_back(a, b);// push_back equivalently for our purpose
if something else happens
v.erase(iterator)
*/
}
void reset(){
v.clear();
}
};
class Main1{
private:
std::vector<std::unique_ptr<Derived>> v;
public:
Main1();
void Do(int i, std::string& b){
/*
if something happens
v.push_back(std::unique_ptr<Derived>(new Derived(i, b)));
if something else happens
v.erase(iterator)
*/
}
void reset(){
v.clear();
}
};
int main()
{
Main m;
for(int i=0; i<101; ++i){
//something
m.Do(i, b);
//something
if(i%10==0)
m.reset(); //The bug is here. If I use Main1 everything runs smoothly
}
return 0;
}
This is a simplified version of the code that creates me problem. I hope that the detail are enough to give the correct contest for the answer.
The debugger points me deep in the code defining what a deconstructor does reporting a segmentation fault, and personally I cannot understand what that code does.
The compiler I am using is g++ 10.1 with the std=c++17 flag.
Error
I can't understand why I'm having this compilation error using Rcpp (version 1.0.2):
From file /home/rmagno/R/x86_64-pc-linux-gnu-library/3.6/Rcpp/include/Rcpp/internal/wrap.h:
Line 523 static assertion failed: cannot convert type to SEXP
Source of the error
I'm trying to wrap this C function glfwSetKeyCallback from the GLFW library.
And I know that the error is stemming somehow from the CPP source file below but I don't understand what I am doing wrong:
glfw_types.h
#ifndef RCPP_GLFW_TYPES_H
#define RCPP_GLFW_TYPES_H
#include <Rcpp.h>
#include <GLFW/glfw3.h>
// https://stackoverflow.com/questions/41210595/s4-object-with-a-pointer-to-a-c-struct
typedef Rcpp::XPtr<GLFWwindow, Rcpp::PreserveStorage, glfwDestroyWindow> GLFWwindow_ptr;
#endif
glfw_set_key_callback.cpp
#include "glfw_types.h"
using namespace Rcpp;
namespace {
std::unique_ptr<Rcpp::Function> key_callback_func_ptr;
}
void glfw_set_key_callback_wrapper(GLFWwindow* window, int key, int scancode, int action, int modes)
{
(*key_callback_func_ptr)(window, key, scancode, action, modes);
}
// [[Rcpp::export]]
void glfw_set_key_callback(GLFWwindow_ptr window, Rcpp::Function key_callback) {
key_callback_func_ptr = std::make_unique<Rcpp::Function>(key_callback);
glfwSetKeyCallback((GLFWwindow*)window, (GLFWkeyfun) glfw_set_key_callback_wrapper);
}
EDIT
The source code below that compiles the function glfw_destroy_window and exports it as glfwDestroyWindow uses the type GLFWwindow_ptr and compiles and works from R just fine.
glfwDestroyWindow.cpp
#include "glfw_types.h"
using namespace Rcpp;
//' #export
// [[Rcpp::export("glfwDestroyWindow")]]
void glfw_destroy_window(GLFWwindow_ptr window) {
glfwDestroyWindow((GLFWwindow*)window);
R_ClearExternalPtr(window);
}
EDIT 2
This function also works fine:
#include "glfw_types.h"
using namespace Rcpp;
//' #export
// [[Rcpp::export("glfwCreateWindow")]]
GLFWwindow_ptr glfw_create_window(int width, int height, std::string title) {
const char *title_c = title.c_str();
return GLFWwindow_ptr(glfwCreateWindow(width, height, title_c, NULL, NULL), true);
}
EDIT 3
This seems to be working...
The new glfw_set_key_callback.cpp
#include "glfw_types.h"
using namespace Rcpp;
namespace {
std::unique_ptr<Rcpp::Function> key_callback_func_ptr;
}
void glfw_set_key_callback_wrapper(GLFWwindow* window, int key, int scancode, int action, int modes)
{
(*key_callback_func_ptr)(GLFWwindow_ptr(window, true), key, scancode, action, modes);
}
// [[Rcpp::export]]
void glfw_set_key_callback(GLFWwindow_ptr window, Rcpp::Function key_callback) {
key_callback_func_ptr = std::make_unique<Rcpp::Function>(key_callback);
glfwSetKeyCallback((GLFWwindow*)window, (GLFWkeyfun) glfw_set_key_callback_wrapper);
}
Any help is greatly appreciated!
#include "glfw_types.h"
using namespace Rcpp;
namespace {
std::unique_ptr<Rcpp::Function> key_callback_func_ptr;
}
void glfw_set_key_callback_wrapper(GLFWwindow* window, int key, int scancode, int action, int modes)
{
(*key_callback_func_ptr)(GLFWwindow_ptr(window, false), key, scancode, action, modes);
}
// [[Rcpp::export]]
void glfw_set_key_callback(GLFWwindow_ptr window, Rcpp::Function key_callback) {
key_callback_func_ptr = std::make_unique<Rcpp::Function>(key_callback);
glfwSetKeyCallback((GLFWwindow*)window, (GLFWkeyfun) glfw_set_key_callback_wrapper);
}
Is it possible to create variadic signal and connect generic lambda as slot? I mean something like (say, all definitions of involved functions are visible where needed (e.g. at points of instantiation)):
#include <QCoreApplication>
#include <QObject>
#include <QTime>
class A
: public QObject
{
Q_OBJECT
public :
A(QObject * const parent = Q_NULLPTR)
: QObject{parent}
{ ; }
signals :
template< typename ...Ts >
void infoMessage(Ts... args);
public slots :
void run()
{
emit infoMessage("Started at ", QTime::currentTime());
}
};
#include <QTimer>
#include <QtDebug>
#include "main.moc"
int main(int argc, char * argv [])
{
QCoreApplication a{argc, argv};
A a;
auto printInfoMessage = [&] (auto... args)
{
(qInfo() << ... << args);
};
QObject::connect(&a, SIGNAL(infoMessage), printInfoMessage);
QTimer::singleShot(0, &a, &A::run);
return a.exec();
}
Currently it gives an error message:
AUTOGEN: error: process for main.cpp:18: Error: Template function as signal or slot
moc failed...
Here macro SLOT() instead of &A::infoMessage does not help a lot. Is there any workarounds to overcome this limitation?
I know, that some of the answers will contain a using of std::make_tuple and std::index_sequence stuff. But is there less verbose solution?
There is no direct workaround for having template. On of thea reason is that the moc indexes all signals and slots, and this cannot be done for function templates as function templates will generate several functions depending code that is generally not accessible from the moc.
I don't think you can make it work with tuple and such as these are also templates.
A solution could be to use QVariant and/or QVariantList for your arguments.
Please note that the error is not caused by the QObject::connect line, but the the signal declaration in class A.
Also, you cannot replace SIGNAL() and SLOT() at your will, it is either a signal or a slot, it cannot be both.
And finally you should be using this form:
QObject::connect(&a, &A::infoMessage, printInfoMessage);
And since printInfoMessage is using auto parameters, you might need to force the auto resolution using qOverload:
QObject::connect(&a, &A::infoMessage, qOverload<QVariantList>(printInfoMessage));
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Im attempting to implement strcpy or strncpy and both are showing an error no matter which i use.
The error is only under strncpy and strcpy
Item.cpp:
#include "Item.h"
#include <iomanip>
#include <iostream>
#include <ctime>
#include <string>
using namespace std;
#include "Date.h"
#include "POS.h"
#include "PosIO.h"
namespace sict {
Item::Item(){
_name = '\0';
_price = 0;
_taxed ='0';
_quantity = '\0';
}
Item::Item(const char* sku, const char * name, double price, bool taxed){
strNcpy(_sku, sku, MAX_SKU_LEN);
name = new char[20];
strcpy(_name, name);
_quantity = 0;
price = _price;
if (price = '\0') {
_taxed = true;
}
}
void Item::sku(const char* value){
strncpy(_sku, value);
}
void Item::price(double p){
p = _price;
}
void Item::name(const char * n){
strcpy(_name, n);
}
}
Any idea how to fix it, ive excluded alot of code from item.cpp thats irrelevant.
Both strcpy and strncpy are declared in the cstring header. You need to include it in order to use the functions:
#include <cstring>
Using std::strcpy();
will solve your issue.
There are two ways to solve this problem, either by including the appropriate header which is #include <cstring> or put std:: in front of the function.
Also, I have noticed that you write strNcpy which can lead to a syntax error.
Is it possible to use a QFile like a std::iostream? I'm quite sure there must be a wrapper out there. The question is where?
I have another libs, which requires a std::istream as input parameter, but in my program i only have a QFile at this point.
I came up with my own solution using the following code:
#include <ios>
#include <QIODevice>
class QStdStreamBuf : public std::streambuf
{
public:
QStdStreamBuf(QIODevice *dev) : std::streambuf(), m_dev(dev)
{
// Initialize get pointer. This should be zero so that underflow is called upon first read.
this->setg(0, 0, 0);
}
protected:
virtual std::streamsize xsgetn(std::streambuf::char_type *str, std::streamsize n)
{
return m_dev->read(str, n);
}
virtual std::streamsize xsputn(const std::streambuf::char_type *str, std::streamsize n)
{
return m_dev->write(str, n);
}
virtual std::streambuf::pos_type seekoff(std::streambuf::off_type off, std::ios_base::seekdir dir, std::ios_base::openmode /*__mode*/)
{
switch(dir)
{
case std::ios_base::beg:
break;
case std::ios_base::end:
off = m_dev->size() - off;
break;
case std::ios_base::cur:
off = m_dev->pos() + off;
break;
}
if(m_dev->seek(off))
return m_dev->pos();
else
return std::streambuf::pos_type(std::streambuf::off_type(-1));
}
virtual std::streambuf::pos_type seekpos(std::streambuf::pos_type off, std::ios_base::openmode /*__mode*/)
{
if(m_dev->seek(off))
return m_dev->pos();
else
return std::streambuf::pos_type(std::streambuf::off_type(-1));
}
virtual std::streambuf::int_type underflow()
{
// Read enough bytes to fill the buffer.
std::streamsize len = sgetn(m_inbuf, sizeof(m_inbuf)/sizeof(m_inbuf[0]));
// Since the input buffer content is now valid (or is new)
// the get pointer should be initialized (or reset).
setg(m_inbuf, m_inbuf, m_inbuf + len);
// If nothing was read, then the end is here.
if(len == 0)
return traits_type::eof();
// Return the first character.
return traits_type::not_eof(m_inbuf[0]);
}
private:
static const std::streamsize BUFFER_SIZE = 1024;
std::streambuf::char_type m_inbuf[BUFFER_SIZE];
QIODevice *m_dev;
};
class QStdIStream : public std::istream
{
public:
QStdIStream(QIODevice *dev) : std::istream(m_buf = new QStdStreamBuf(dev)) {}
virtual ~QStdIStream()
{
rdbuf(0);
delete m_buf;
}
private:
QStdStreamBuf * m_buf;
};
I works fine for reading local files. I haven't tested it for writing files. This code is surely not perfect but it works.
I came up with my own solution (which uses the same idea Stephen Chu suggested)
#include <iostream>
#include <fstream>
#include <cstdio>
#include <QtCore>
using namespace std;
void externalLibFunction(istream & input_stream) {
copy(istream_iterator<string>(input_stream),
istream_iterator<string>(),
ostream_iterator<string>(cout, " "));
}
ifstream QFileToifstream(QFile & file) {
Q_ASSERT(file.isReadable());
return ifstream(::_fdopen(file.handle(), "r"));
}
int main(int argc, char ** argv)
{
QFile file("a file");
file.open(QIODevice::WriteOnly);
file.write(QString("some string").toLatin1());
file.close();
file.open(QIODevice::ReadOnly);
std::ifstream ifs(QFileToifstream(file));
externalLibFunction(ifs);
}
Output:
some string
This code uses std::ifstream move constructor (C++x0 feature) specified in 27.9.1.7 basic_ifstream constructors section of Working Draft, Standard for Programming Language C++:
basic_ifstream(basic_ifstream&& rhs);
Effects: Move constructs from the
rvalue rhs. This is accomplished by
move constructing the base class, and
the contained basic_filebuf. Next
basic_istream::set_rdbuf(&sb) is called to install the contained
basic_filebuf.
See How to return an fstream (C++0x) for discussion on this subject.
If the QFile object you get is not open for read already, you can get filename from it and open an ifstream object.
If it's already open, you can get file handle/descriptor with handle() and go from there. There's no portable way of getting a fstream from platform handle. You will have to find a workaround for your platforms.
Here's a good guide for subclassing std::streambuf to provide a non-seekable read-only std::istream: https://stackoverflow.com/a/14086442/316578
Here is a simple class based on that approach which adapts a QFile into an std::streambuf which can then be wrapped in an std::istream.
#include <iostream>
#include <QFile>
constexpr qint64 ERROR = -1;
constexpr qint64 BUFFER_SIZE = 1024;
class QFileInputStreamBuffer final : public std::streambuf {
private:
QFile &m_file;
QByteArray m_buffer;
public:
explicit QFileInputStreamBuffer(QFile &file)
: m_file(file),
m_buffer(BUFFER_SIZE, Qt::Uninitialized) {
}
virtual int underflow() override {
if (atEndOfBuffer()) {
// try to get more data
const qint64 bytesReadIntoBuffer = m_file.read(m_buffer.data(), BUFFER_SIZE);
if (bytesReadIntoBuffer != ERROR) {
setg(m_buffer.data(), m_buffer.data(), m_buffer.data() + bytesReadIntoBuffer);
}
}
if (atEndOfBuffer()) {
// no more data available
return std::char_traits<char>::eof();
}
else {
return std::char_traits<char>::to_int_type(*gptr());
}
}
private:
bool atEndOfBuffer() const {
return gptr() == egptr();
}
};
If you want to be able to more things like seek, write, etc., then you'd need one of the other more complex solutions here which override more streambuf functions.
If you don't care much for performance you can always read everything from the file and dump it into an std::stringstream and then pass that to your library. (or the otherway, buffer everything to a stringstream and then write to a QFile)
Other than that, it doesn't look like the two can inter-operate. At any rate, Qt to STL inter operations are often a cause for obscure bugs and subtle inconsistencies if the version of STL that Qt was compiled with is different in any way from the version of STL you are using. This can happen for instance if you change the version of Visual Studio.