Given the following sample code:
#include <iostream>
#include <memory>
using namespace std;
struct A {
public:
A(int aa) : a(aa) {}
int a;
virtual ~A() {}
};
struct B : A {
public:
B(int aa, int bb) : A(aa), b(bb) {}
int b;
};
void f(shared_ptr<A> a){
shared_ptr<B> b = dynamic_pointer_cast<B>(a);
if (b) {
cout << b->b << endl;
} else {
cout << a->a << endl;
}
}
int main() {
auto a = make_shared<A>(3);
auto b = make_shared<B>(7, 4);
f(a);
f(b);
return 0;
}
Eclipse indicates that there is an error on the line
f(b);
saying Invalid arguments ' Candidates are: void f(std::shared_ptr<A>) '
because a shared_ptr<B> has been passed. This compiles and runs, and has output:
3
4
as expected.
The indexer and compiler have -std=c++11 specified.
The compiler also has the symbol __GXX_EXPERIMENTAL_CXX0X__ defined.
Is there any way to get rid of this error and its red squiggles in Eclipse (preferably without modifying the source)?
This has been fixed in later versions of CDT (I just tried it).
You can use a nightly build of CDT using this repository:
Go to Help, and enter the url http://download.eclipse.org/tools/cdt/builds/kepler/nightly
If you don't feel like using a nighty build, you should at least make sure you have the latest released version (at this writing it is 8.1.1), using http://download.eclipse.org/tools/cdt/releases/juno/
My full setup of eclipse with C++11 is found here:
http://scrupulousabstractions.tumblr.com/post/36441490955/eclipse-mingw-builds
I recommend you disable the Static Code Analysis plugin Codan in the settings it probably does not support C++11 yet.
Related
Run the the following C++ program twice. Once with the given destructor and once with std::fesetround(value); removed from the destructor. Why do I receive different outputs? Shouldn't destructor be called after function add? I ran both versions on http://cpp.sh/ and Clang++ 6.0, and g++ 7.2.0. For g++, I also included #pragma STDC FENV_ACCESS on in the source code, nothing changed.
#include <iostream>
#include <string>
#include <cfenv>
struct raii_feround {
raii_feround() : value(std::fegetround()) { }
~raii_feround() { std::fesetround(value); }
inline void round_up () const noexcept { std::fesetround(FE_UPWARD ); }
inline void round_down() const noexcept { std::fesetround(FE_DOWNWARD); }
template<typename T>
T add(T fst, T snd) const noexcept { return fst + snd; }
private:
int value; };
float a = 1.1;
float b = 1.2;
float c = 0;
float d = 0;
int main() {
{
raii_feround raii;
raii.round_up();
c = raii.add(a, b);
}
{
raii_feround raii;
raii.round_down();
d = raii.add(a, b);
}
std::cout << c << "\n"; // Output is: 2.3
std::cout << d << "\n"; // Output is: 2.3 or 2.29999
}
Using the floating-point environment facilities requires inserting #pragma STDC FENV_ACCESS on into the source (or ensure that they default to on for the implementation you are using. (Although STDC is a C feature, the C++ standard says that these facilities are imported into C++ by the <cfenv> header.)
Doing so at cpp.sh results in “warning: ignoring #pragma STDC FENV_ACCESS [-Wunknown-pragmas]”.
Therefore, accessing and modifying the floating-point environment is not supported by the compiler at cpp.sh.
All I needed to do was to do std::cout << std::setprecision(30); before calling std::cout in the code (iomanip should be included as well).
I was given sample code in a C++ course I am taking. I can get it to build in CodeBlocks but not in Visual Studio 2015. In Visual Studio the main line "rename test3;" raises an error looking for a semicolon and the variable declaration in that line, "rename", is not highlighted in the default green for a type as it should be. Same for the next line. Therefore test3 and test4 come up as undefined. If I remove "#include <iostream>" "rename" turns to green in lines 33 and 34 but then the std include become undefined. Implementing "using namespace std" doesn't help either. I am attempting to get rid of "using namespace std" as it is not good coding practice from what I understand around here. I am missing a VS setting I think.
//#include <iostream> // original first two line
//using namespace std; //
#include <iostream>
#include <cstring> // I added this include
using std::cin; // I added the following using lines
using std::cout;
using std::endl;
class feature { // this class has a specific feature
private:
char data[16];
public:
feature() { strcpy(data, "default"); }
feature(char * in) { strcpy(data, in); } // error checks needed
void set(char * in) { strcpy(data, in); }
void out() { cout << data << endl; }
};
class rename : private feature {
public:
void reset(char * in) { set(in); }
void print() { out(); }
rename() : feature() {}
rename(char * in) : feature(in) {}
};
int main() {
feature test1;
feature test2("test2 data");
rename test3;
rename test4("test4 data");
test1.out();
test2.out();
test3.print();
test4.print();
}
The results should be:
default
test2 data
default
test4 data
default
test4 data
If I change back to the original first two lines the code does not work. If I rename "rename" to "rename1" then the code works.
#include <iostream>
using namespace std;
class feature { // this class has a specific feature
private:
char data[16];
public:
feature() { strcpy(data, "default"); }
feature(char * in) { strcpy(data, in); } // error checks needed
void set(char * in) { strcpy(data, in); }
void out() { cout << data << endl; }
};
class rename1 : private feature {
public:
void reset(char * in) { set(in); }
void print() { out(); }
rename1() : feature() {}
rename1(char * in) : feature(in) {}
};
int main() {
feature test1;
feature test2("test2 data");
rename1 test3;
rename1 test4("test4 data");
test1.out();
test2.out();
test3.print();
test4.print();
}
rename is a function that gets included by the header <cstring> in Visual Studio, which causes a conflict with the name of your class. You therefore need to change the name of your derived class. Visual Studio will probably also require you to change strcpy to strcpy_s (it may either give a Warning or Error otherwise).
Ideally you should avoid using C compatibility headers in new code you write (unless you absolutely need them), e.g.: in your example you should stick to std::string instead of char*
I have encountered a problem while was using variadic templates, but the problem is not related to variadic templates and can be reproduced without them.
The problem is related to same names of types in inherited and base classes.
I've simplified code to the following snippet:
#include <typeinfo>
#include <iostream>
struct A
{
int member;
};
struct B: public A
{
typedef A NEXT;
short member;
};
struct Foo: public B
{
typedef B NEXT;
void Check()
{
std::cout << typeid(NEXT::member).name() << '\n';
std::cout << typeid(NEXT::NEXT::member).name() << '\n';
NEXT::NEXT::member = 1;
NEXT::member = 2;
std::cout << NEXT::NEXT::member << '\n';
std::cout << NEXT::member << '\n';
};
};
int main()
{
Foo foo;
foo.Check();
}
It compiles without warnings and works with GCC and clang, but it produces wrong output with MSVC (at least with Visual Studio 2015 Update 1).
It seems that some collision in names happens, and it treats NEXT::NEXT::member as NEXT::member, but in the same place, it lies to typeid (as well as to std::is_same).
When compiled with GCC or clang the output is:
s
i
1
2
But in case of MSVC, the output is:
short
int
2
2
The following code compiles without warnings with GCC or clang, but as expected produces error with MSVC:
struct A
{
int member;
};
struct B: public A
{
typedef A NEXT;
short member;
};
struct Foo: public B
{
typedef B NEXT;
short& GetB() { return NEXT::member; };
int& GetA() { return NEXT::NEXT::member; };
};
The MSVC error:
source_file.cpp(18): error C2440: 'return': cannot convert from 'short' to 'int &'
Is the code above valid? Is it a problem of MSVC or I'm utilizing UB somehow?
Update
The problem can not be reproduced in MSVC 2015 update 3.
When i compile the code below, i got the error like Type qualifier 'std' must be a struct or class name. Kindly find the code below-
#include <iostream>
int foo(int i)
{
return 2;
}
double foo(double d)
{
return 4.0;
}
struct Computer
{
int foo(int i)
{
return 8;
}
};
struct Gateway : public Computer
{
double foo(double d)
{
return 16.0;
}
};
int main(int argc, char** argv)
{
Gateway g;
std::cout << foo(1) + foo(1.0) + g.foo(1) + g.foo(1.0) << std::endl;
return 0;
}
Kindly check it and suggest how to resolve it.
Your code compiles and runs fine.
You are getting this error because your compiler is not compliant with the C++ standard.
Turbo C++ is horrendously outdated.
It is time to get a new, free, standard compliant compiler. Clang for example.
In answer to your second question, in the comments, Gateway::foo hides Computer::foo, which is why Gateway::foo is invoked for both int and double arguments. If this is not what you intended, you could alter your struct like so:
struct Gateway : public Computer
{
using Computer::foo;
double foo(double d)
{
return 16.0;
}
};
See it run!
I'm getting a runtime error ("memory can't be written") that, after inspection through the debugger, leads to the warning in the tittle.
The headers are the following:
componente.h:
#ifndef COMPONENTE_H
#define COMPONENTE_H
using namespace std;
class componente
{
int num_piezas;
int codigo;
char* proovedor;
public:
componente();
componente(int a, int b, const char* c);
virtual ~componente();
virtual void print();
};
#endif // COMPONENTE_H
complement.h implementation
#include "Componente.h"
#include <string.h>
#include <iostream>
componente::componente()
{
num_piezas = 0;
codigo = 0;
strcpy(proovedor, "");
//ctor
}
componente::componente(int a = 0, int b = 0, const char* c = "")
{
num_piezas = a;
codigo = b;
strcpy(proovedor, "");
}
componente::~componente()
{
delete proovedor;//dtor
}
void componente::print()
{
cout << "Proovedor: " << proovedor << endl;
cout << "Piezas: " << num_piezas << endl;
cout << "Codigo: " << codigo << endl;
}
teclado.h
#ifndef TECLADO_H
#define TECLADO_H
#include "Componente.h"
class teclado : public componente
{
int teclas;
public:
teclado();
teclado(int a, int b, int c, char* d);
virtual ~teclado();
void print();
};
#endif // TECLADO_H
teclado.h implementation
#include "teclado.h"
#include <iostream>
teclado::teclado() : componente()
{
teclas = 0;//ctor
}
teclado::~teclado()
{
teclas = 0;//dtor
}
teclado::teclado(int a = 0, int b = 0, int c = 0, char* d = "") : componente(a,b,d)
{
teclas = c;
}
void teclado::print()
{
cout << "Teclas: " << teclas << endl;
}
The main method where I get the runtime error is the following:
#include <iostream>
#include "teclado.h"
using namespace std;
int main()
{
componente a; // here I have the breakpoint where I check this warning
a.print();
return 0;
}
BUT, if instead of creating an "componente" object, I create a "teclado" object, I don't get the runtime error. I STILL get the warning during debugging, but the program behaves as expected:
#include <iostream>
#include "teclado.h"
using namespace std;
int main()
{
teclado a;
a.print();
return 0;
}
This returns "Teclas = 0" plus the "Press any key..." thing.
Do you have any idea why the linker is having troube with this? It doesn't show up when I invoke the virtual function, but before, during construction.
Two errors that I can see:
strcpy(proovedor, ""); // No memory has been allocated to `proovedor` and
// it is uninitialised.
As it is uninitialised this could be overwriting anywhere in the process memory, so could be corrupting the virtual table.
You could change this to (in both constructors):
proovedor = strdup("");
Destructor uses incorrect delete on proovedor:
delete proovedor; // should be delete[] proovedor
As this is C++ you should considering using std::string instead of char*.
If you do not change to std::string then you need to either:
Implement a copy constructor and assignment operator as the default versions are incorrect if you have a member variable that is dynamically allocated, or
Make the copy constructor and assignment operator private to make it impossible for them to be used.
Another source of this same message is that gdb can get confused by not-yet-initialized variables. (This answers the question title, but not the OP's question, since a web search led me here looking for an answer.)
Naturally, you shouldn't have uninitialized variables, but in my case gdb attempts to show function local variables even before they are declared/initialized.
Today I'm stepping through another developer's gtest case and this message was getting dumped to output every time the debugger stopped. In this case, the variable in question was declared on ~line 245, but the function started on ~line 202. Every time I stopped the debugger between these lines, I received the message.
I worked around the issue by moving the variable declaration to the top of the function.
For reference, I am testing with gdb version 7.11.1 in QtCreator 4.1.0 and I compiled with g++ version 5.4.1