consider the following: I have a class A with a constructor which takes an array of ints of size 3 as argument.
Now I want to construct a shared_ptr to A. If I use
shared_ptr<>(new A (parameter))
everything is fine.
But if I try using
make_shared<A>(parameter)
the compiler gives an error message. This happens only if the parameter-array is declared on the stack AND with a variable as array size (int parameter [n])
The problem disappears when using static arrays (int parameter[3]) or allocating the array on the heap with new.
I mean, this is no serious issue as there are the mentioned workarounds. Still, I would appreciate any explanation on why whis happens...
Btw I'm using g++ 4.8.2.
Here is a minimal example and the error log:
#include <iostream>
#include <memory>
using namespace std;
// some simple class
class A
{
public:
A () {};
A (int var[3]) {}; // some non-default constructor with an array as argument
void foo (){cout << "foo()" << endl;};
};
int main()
{
// make a shared_ptr to A
shared_ptr<A> ptr;
// allocate an array var1 of size nVars=3 on the stack
int nVars = 3;
int var1[nVars];
ptr = shared_ptr<A> (new A(var1)); // without make_shared, the c'tor is recognized
ptr->foo();
ptr = make_shared<A> (var1); // <- error at compile time!
ptr->foo();
// same with static array var2 of size 3
int var2[3];
ptr = make_shared<A> (var2); // <- no compilation error
ptr->foo();
// same with dynamic array var3 of size 3
int* var3 = new int[nVars];
ptr = make_shared<A> (var3); // <- no compilation error
ptr->foo();
return 0;
}
build log:
g++ -std=c++0x -D__GXX_EXPERIMENTAL_CXX0X__ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o "main.o" "../main.cpp"
../main.cpp: In function ‘int main()’:
../main.cpp:25:28: error: no matching function for call to ‘make_shared(int [(((sizetype)(((ssizetype)nVars) + -1)) + 1)])’
ptr = make_shared<A> (var1); // <- error at compile time!
^
../main.cpp:25:28: note: candidate is:
In file included from /usr/include/c++/4.8/memory:82:0,
from ../main.cpp:2:
/usr/include/c++/4.8/bits/shared_ptr.h:610:5: note: template<class _Tp, class ... _Args> std::shared_ptr<_Tp1> std::make_shared(_Args&& ...)
make_shared(_Args&&... __args)
^
/usr/include/c++/4.8/bits/shared_ptr.h:610:5: note: template argument deduction/substitution failed:
../main.cpp:25:28: note: variable-sized array type ‘int (&)[(((sizetype)(((ssizetype)nVars) + -1)) + 1)]’ is not a valid template argument
ptr = make_shared<A> (var1); // <- error at compile time!
^
Cheers and thanks in advance for your answers!
Juri
Related
I want to keep all the warnings enabled so -Wno-array-bound is not an option for me.
I am using variable size array work around using a structure (zero size array in a struct) and this is causing me to run causing me warnings.
Is there an attribute method to suppress these warnings where they occur?
To reproduce the warning:
#include <iostream>
struct A
{
int a;
char ch[0];
};
int main()
{
volatile A* test = (A*)malloc(sizeof(A) + (sizeof(char) * 10));
test->a = 1;
test->ch[0] = 'a';
}
Compile with:
g++ -O2 -Warray-bounds=2 t.cpp
warning generated:
t.cpp: In function ‘int main()’:
t.cpp:30:15: warning: array subscript 0 is above array bounds of ‘volatile char [0]’ [-Warray-bounds]
30 | test->ch[0] = 'a';
| ~~~~~~~~~~^
I'm trying to write a function that embeds the Octave interpreter in C++, as described here https://octave.org/doc/v4.0.1/Standalone-Programs.html .
I'm trying to do this from a program that I'm writing in Eclipse, and trying to compile with GCC on Linux. I want to be able to call an external script, as in the second example in the link.
My code so far looks like this.....
#include <iostream>
#include <oct.h>
#include <octave.h>
#include <parse.h>
#include <interpreter.h>
using namespace std;
class OctaveInt {
public:
void callOctave (double, int, string);
OctaveInt(string path );
private:
octave::interpreter interpreter;
};
// Member functions including constructor..
OctaveInt::OctaveInt(string path)
{
// Constructor - initialises engine and sets path
int status = interpreter.execute();
octave_value_list p;
p(0) = path;
octave_value_list o1 = octave::feval ("addpath", p);
}
void OctaveInt::callOctave(double params, int size, string name) {
std::cout << "Hello World" << std::endl;
int n = 2;
octave_value_list in;
octave_value_list p;
for (octave_idx_type i=0; i < size; i++)
in(i) = octave_value(params[i]);
octave_value_list out = octave::feval (name, in);
std::cout << "Output is ";
std::cout << out(0).int_value();
}
int main() {
double params[] = {100, 2, 3, 4, 5, 6};
int size = 6;
string path = "/home/arwel/eclipseWorkspace_new/octaveCaller/src/";
OctaveInt octI(path);
octI.callOctave(params, size, "myFunction");
return 0;
}
When I try to compile however, I get a series of errors.....
Invoking: GCC C++ Compiler
g++ -std=c++0x -I/usr/include/octave-5.2.0/octave/ -I/usr/share/octave/5.2.0/etc/tests -I/usr/lib/x86_64-redhat-linux6E -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/octaveCaller.d" -MT"src/octaveCaller.o" -o "src/octaveCaller.o" "../src/octaveCaller.cpp"
../src/octaveCaller.cpp: In constructor ‘OctaveInt::OctaveInt(std::string)’:
../src/octaveCaller.cpp:31:6: warning: unused variable ‘status’ [-Wunused-variable]
int status = interpreter.execute();
^
../src/octaveCaller.cpp: In member function ‘void OctaveInt::callOctave(double, int, std::string)’:
../src/octaveCaller.cpp:48:32: error: invalid types ‘double[octave_idx_type {aka long int}]’ for array subscript
in(i) = octave_value(params[i]);
^
../src/octaveCaller.cpp:42:6: warning: unused variable ‘n’ [-Wunused-variable]
int n = 2;
^
../src/octaveCaller.cpp: In function ‘int main()’:
../src/octaveCaller.cpp:65:44: error: no matching function for call to ‘OctaveInt::callOctave(double [6], int&, const char [11])’
octI.callOctave(params, size, "myFunction");
^
../src/octaveCaller.cpp:65:44: note: candidate is:
../src/octaveCaller.cpp:38:6: note: void OctaveInt::callOctave(double, int, std::string)
void OctaveInt::callOctave(double params, int size, string name) {
^
../src/octaveCaller.cpp:38:6: note: no known conversion for argument 1 from ‘double [6]’ to ‘double’
make: *** [src/octaveCaller.o] Error 1
"make all" terminated with exit code 2. Build might be incomplete.
12:41:36 Build Failed. 3 errors, 2 warnings. (took 1s.927ms)
So it looks like I have some problems with types of variables (??).
I don't really know much C++, so I'm undoubtedly doing some basic C++ mistake. Can someone give me a hand to figure out what I'm doing wrong?
The below code works perfectly with strings but with char it gives segmentation fault.
#include<iostream>
using namespace std;
class salary
{
public:
int empno;
float inctax;
float netsal;
int gross;
short int age;
char name[50];
salary(){
empno=0;
gross=0;
age=0;
strcpy(name,'\0');
}
salary(int empn,int gros,short int ag,char nam[]){
empno=empn;
gross=gros;
age=ag;
strcpy(name,nam);
}
void calc(){
inctax=0.0;
if(gross>1000000)
inctax=0.3*gross;
else if(gross>=500000 && gross<=1000000)
inctax=0.2*gross;
else if(gross>=250000 && gross<500000)
inctax=0.1*gross;
else
inctax=0.0;
netsal=gross-inctax;
cout<<"inctax"<<inctax;
cout<<"net sal"<<netsal;
}
};
int main(){
salary *r=new salary();
salary *r1=new salary(112,500000,21,"Arnab");
r1->calc();
return 0;
}
I agree with vu1p3n0x's comment,
the problem is in the default constructor.
strcpy(name, '\0'); // This is wrong!
strcpy() takes two char arrays as arguments, but a character itself was passed as the second argument in your code.
The syntax of strcpy() is:
char * strcpy ( char * destination, const char * source );
In order to create null string using char arrays, you should probably use,
strcpy(name, "\0");
/*or*/
name[0] = '\0';
More on copying string, Reference and tutorialspoint
Your main problem is that your compiler isn't telling you about the obvious errors in the code. If you have correctly told it to report errors, then you perhaps need a better compiler. Here's the output I get when I compile:
g++ -std=c++14 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses 38113648.cpp -o 38113648
38113648.cpp: In constructor ‘salary::salary()’:
38113648.cpp:18:25: error: ‘strcpy’ was not declared in this scope
strcpy(name,'\0');
^
38113648.cpp: In constructor ‘salary::salary(int, int, short int, char*)’:
38113648.cpp:25:24: error: ‘strcpy’ was not declared in this scope
strcpy(name,nam);
^
38113648.cpp: In function ‘int main()’:
38113648.cpp:46:48: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
salary *r1=new salary(112,500000,21,"Arnab");
^
38113648.cpp:45:13: warning: unused variable ‘r’ [-Wunused-variable]
salary *r=new salary();
^
When I add
#include <cstring>
and change the constructor to take char const[], I get
g++ -std=c++14 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses 38113648.cpp -o 38113648
38113648.cpp: In constructor ‘salary::salary()’:
38113648.cpp:19:25: warning: null argument where non-null required (argument 2) [-Wnonnull]
strcpy(name,'\0');
^
Obviously you meant that to be "\0". Better still, provide an initializer:
salary()
: empno{0},
gross{0},
age{0},
name{0}
{
}
salary(int empno, int gross, short int age, char const name[])
: empno{empno},
gross{gross},
age{age}
{
strcpy(this->name, name);
}
(I've also given the formal parameters more meaningful names, as this often forms the documentation of the constructor).
Adding -Weffc++ may also be worthwhile - in this case it warns that you don't initialize inctax or netsal in the constructors. If you're happy to have part-initialized objects, you'll obviously need to use Valgrind to check that these values are indeed set before they are used, because it can't be determined statically.
This question already has an answer here:
Pass anonymous function object to std::function?
(1 answer)
Closed 7 years ago.
What I am trying to achieve is to make a functor that can take different functors as arguments.
Edit: the reason for my problem, the "most vexing parse", and the solution are well-described: see this question and answer, the whole most-vexing-parse tag, and even the wikipedia page. Still, I was not able to identify the problem before asking, and will leave this question as it might help others.
What I did:
In a header file functor.hpp:
#ifndef FUNCTOR_HPP
#define FUNCTOR_HPP
#include <functional>
template <typename T, typename BinOp = typename std::plus<T>>
struct doer {
BinOp op;
doer(BinOp o = std::plus<T>()) : op(o) {}
T operator()(const T& a, const T& b) const
{ return op(a, b); }
};
#endif // FUNCTOR_HPP
With this header, I can write a program functor.cpp like this:
#include <iostream>
#include "functor.hpp"
int main()
{
doer<int> f;
std::cout << f(3, 7) << std::endl;
}
and I can compile and run it to get, as expected:
$ make functor
g++ -std=c++14 -pedantic -Wall functor.cpp -o functor
$ ./functor
10
$
I am struggling to find a way to instantiate my doer with a different operator (not std::plus<T>).
doer<int, std::multiplies<int>> f2(std::multiplies<int>());
This compiles without a problem, but I have not been able to figure out a way to call f2(3, 7), to get the product 21. For example, if I add another line to the program:
int r = f2(3, 7);
and try to compile, I get:
$ make functor
g++ -std=c++14 -pedantic -Wall functor.cpp -o functor
functor.cpp: In function ‘int main()’:
functor.cpp:10:20: error: invalid conversion from ‘int’ to ‘std::multiplies<int> (*)()’ [-fpermissive]
int r = f2(3, 7);
^
functor.cpp:10:20: error: too many arguments to function ‘doer<int, std::multiplies<int> > f2(std::multiplies<int> (*)())’
functor.cpp:9:37: note: declared here
doer<int, std::multiplies<int>> f2(std::multiplies<int>());
^
functor.cpp:10:20: error: cannot convert ‘doer<int, std::multiplies<int> >’ to ‘int’ in initialization
int r = f2(3, 7);
^
What is going on? Seems almost like f2(3, 7) somehow is not calling the overloaded operator()...
Most vexing parse. Try this:
doer<int, std::multiplies<int>> f2((std::multiplies<int>()));
or this:
doer<int, std::multiplies<int>> f2 = std::multiplies<int>();
or this:
doer<int, std::multiplies<int>> f2{std::multiplies<int>()};
My constructor takes an std::array. I'm trying to give it a default value, but calling the constructor without an argument gives this error:
$ g++ -std=c++11 -Wall -Werror -Wextra -pedantic-errors test.cpp Position.cpp -o test
test.cpp: In function ‘int main()’:
test.cpp:14:29: error: array must be initialized with a brace-enclosed initializer
Position *y = new Position();
^
test.cpp:14:29: error: too many initializers for ‘std::array<unsigned char, 8ul>’
Line numbers are different. This is my code:
// test.cpp
int main() {
Position *x = new Position({1,1,1,1,1,1,1,1}); // works
Position *y = new Position(); // does not work
}
// Position.cpp
#include <cstdint>
#include <array>
#include "Position.h"
Position::Position( std::array<uint8_t,8> columns_ ) {
columns = columns_;
}
// Position.h
#ifndef POSITION_H
#define POSITION_H
#include <array>
class Position {
public:
Position( std::array<uint8_t,8> = {0,0,0,0,0,0,0,0} );
private:
std::array<uint8_t,8> columns;
};
#endif
What have I got wrong?
You need to repeat the type:
Position( std::array<uint8_t,8> = std::array<uint8_t,8>{0,0,0,0,0,0,0,0} );
while this (or using double-braces) works, it creates a copy on each caller's side when the default is taken. An overloaded constructor would avoid this kind of code-bloat, hence I'd advice to prefer overloads over default parameters.
double-braces required for the second case to run:
Position( std::array<uint8_t,8> = {{0,0,0,0,0,0,0,0}} );