I am keeping track if instances of my class using std::vector to store pointers to all of the class objects. I'm wrapping things up and want to remove the pointer in the destructor... but I am getting the following error:
Brazos.cpp:15:89: error: cannot convert 'std::vector::iterator {aka __gnu_cxx::__normal_iterator >}' to 'const char*' for argument '1' to 'int remove(const char*)'
instanceAddress.erase(std::remove(instanceAddress.begin(), instanceAddress.end(), this) instanceAddress.end());
it seems I may need to dereference the iterator... Here is my code:
std::vector<Brazos*> Brazos::instanceAddress;
Brazos::Brazos(Mano mano)
{
instanceAddress.push_back(this);
_mano = mano;
}
Brazos::~Brazos(void)
{
instanceAddress.erase(std::remove(instanceAddress.begin(), instanceAddress.end(), this) instanceAddress.end());
}
You're missing a comma:
instanceAddress.erase(std::remove(instanceAddress.begin(), instanceAddress.end(), this), instanceAddress.end());
^
Also, the error message refers to int std::remove(const char*), so make sure you have #include <algorithm> for the correct std::remove.
Related
In a very simple situation with a constrained constructor, testing for convertibility of the argument, an error is produced in clang, but not in g++:
#include <type_traits>
template <class T, class U>
constexpr bool Convertible = std::is_convertible<T,U>::value && std::is_convertible<U,T>::value;
template <class T>
struct A
{
template <class S, class = std::enable_if_t<Convertible<S,T>> >
A(S const&) {}
};
int main()
{
A<double> s = 1.0;
}
Maybe this issue is related to Is clang's c++11 support reliable?
The error clang gives, reads:
error: no member named 'value' in 'std::is_convertible<double, A<double> >'
constexpr bool Convertible = std::is_convertible<T,U>::value && std::is_convertible<U,T>::value;
~~~~~~~~~~~~~~~~~~~~~~~~~~^
I've tried
g++-5.4, g++-6.2 (no error)
clang++-3.5, clang++-3.8, clang++-3.9 (error)
with argument -std=c++1y and for clang either with -stdlib=libstdc++ or -stdlib=libc++.
Which compiler is correct? Is it a bug in clang or gcc? Or is the behavior for some reasons undefined and thus both compilers correct?
First of all, note that it works fine if you use:
A<double> s{1.0};
Instead, the error comes from the fact that you are doing this:
A<double> s = 1.0;
Consider the line below (extracted from the definition of Convertible):
std::is_convertible<U,T>::value
In your case, this is seen as it follows (once substitution has been performed):
std::is_convertible<double, A<double>>::value
The compiler says this clearly in the error message.
This is because a temporary A<double> is constructed from 1.0, then it is assigned to s.
Note that in your class template you have defined a (more or less) catch-all constructor, so a const A<double> & is accepted as well.
Moreover, remember that a temporary binds to a const reference.
That said, the error happens because in the context of the std::enable_if_t we have that A<double> is an incomplete type and from the standard we have this for std::is_convertible:
From and To shall be complete types [...]
See here for the working draft.
Because of that, I would say that it's an undefined behavior.
As a suggestion, you don't need to use std::enable_if_t in this case.
You don't have a set of functions from which to pick the best one up in your example.
A static_assert is just fine and error messages are nicer:
template <class S>
A(S const&) { static_assert(Convertible<S,T>, "!"); }
When I initialize the std::string member of a class calling its C string constructor, I receive the following errors:
error: expected identifier before string constant
error: expected ',' or '...' before string constant
Although, the program compiles successfully when I use copy initialization or list initialization.
class Element
{
private:
std::string sName_("RandomName"); // Compile error
std::string sName_ = "RandomName"; // OK
std::string sName_{"RandomName"}; // OK
}
What seems to be the problem?
UPDATE
Now I realize this is a stupid question, because, as #p512 says, the compiler will see it as a erroneous method declaration. But I think this question should remain for other people that will do the same thinking error.
std::string sName_("RandomName");
This is an erroneous function declaration - at least that's what the compiler makes of it. Instead you can use something like this:
std::string sName_ = std::string("RandomName");
You can also use initializer lists in the constructor of your class:
class A {
public:
A() : sName_("RandomName") {}
std::string sName_;
};
You can find more on that here: http://en.cppreference.com/w/cpp/language/initializer_list
Why am I getting a warning about initialization in one case, but not the other? The code is in a C++ source file, and I am using GCC 4.7 with -std=c++11.
struct sigaction old_handler, new_handler;
The above doesn't produce any warnings with -Wall and -Wextra.
struct sigaction old_handler={}, new_handler={};
struct sigaction old_handler={0}, new_handler={0};
The above produces warnings:
warning: missing initializer for member ‘sigaction::__sigaction_handler’ [-Wmissing-field-initializers]
warning: missing initializer for member ‘sigaction::sa_mask’ [-Wmissing-field-initializers]
warning: missing initializer for member ‘sigaction::sa_flags’ [-Wmissing-field-initializers]
warning: missing initializer for member ‘sigaction::sa_restorer’ [-Wmissing-field-initializers]
I've read through How should I properly initialize a C struct from C++?, Why is the compiler throwing this warning: "missing initializer"? Isn't the structure initialized?, and bug reports like Bug 36750. Summary: -Wmissing-field-initializers relaxation request. I don't understand why the uninitialized struct is not generating a warning, while the initialized struct is generating a warning.
Why is the uninitialized structs not generating a warning; and why is the initialized structs generating a warning?
Here is a simple example:
#include <iostream>
struct S {
int a;
int b;
};
int main() {
S s { 1 }; // b will be automatically set to 0
// and that's probably(?) not what you want
std::cout<<"s.a = "<<s.a<<", s.b = "<<s.b<<std::endl;
}
It gives the warning:
missing.cpp: In function ‘int main()’:
missing.cpp:9:11: warning: missing initializer for member 'S::b' [-Wmissing-field-initializers]
The program prints:
s.a = 1, s.b = 0
The warning is just a reminder from the compiler that S has two members but you only explicitly initialized one of them, the other will be set to zero. If that's what you want, you can safely ignore that warning.
In such a simple example, it looks silly and annoying; if your struct has many members, then this warning can be helpful (catching bugs: miscounting the number of fields or typos).
Why is the uninitialized structs not generating a warning?
I guess it would simply generate too much warnings. After all, it is legal and it is only a bug if you use the uninitialized members. For example:
int main() {
S s;
std::cout<<"s.a = "<<s.a<<", s.b = "<<s.b<<std::endl;
}
missing.cpp: In function ‘int main()’:
missing.cpp:10:43: warning: ‘s.S::b’ is used uninitialized in this function [-Wuninitialized]
missing.cpp:10:26: warning: ‘s.S::a’ is used uninitialized in this function [-Wuninitialized]
Even though it did not warn me about the uninitialized members of s, it did warn me about using the uninitialized fields. All is fine.
Why is the initialized structs generating a warning?
It warns you only if you explicitly but partially initialize the fields. It is a reminder that the struct has more fields than you enumerated. In my opinion, it is questionable how useful this warning is: It can indeed generate too much false alarms. Well, it is not on by default for a reason...
That's a defective warning. You did initialize all the members, but you just didn't have the initializers for each member separately appear in the code.
Just ignore that warning if you know what you are doing. I regularly get such warnings too, and I'm upset regularly. But there's nothing I can do about it but to ignore it.
Why is the uninitialized struct not giving a warning? I don't know, but most probably that is because you didn't try to initialize anything. So GCC has no reason to believe that you made a mistake in doing the initialization.
You're solving the symptom but not the problem. Per my copy of "Advanced Programming in the UNIX Environment, Second Edition" in section 10.15:
Note that we must use sigemptyset() to initialize the sa_mask member of the structure. We're not guaranteed that act.sa_mask = 0 does the same thing.
So, yes, you can silence the warning, and no this isn't how you initialize a struct sigaction.
The compiler warns that all members are not initialized when you initialize the struct. There is nothing to warn about declaring an uninitialized struct. You should get the same warnings when you (partially) initialize the uninitialized structs.
struct sigaction old_handler, new_handler;
old_handler = {};
new_handler = {};
So, that's the difference. Your code that doesn't produce the warning is not an initialization at all. Why gcc warns about zero initialized struct at all is beyond me.
The only way to prevent that warning (or error, if you or your organization is treating warnings as errors (-Werror option)) is to memset() it to an init value. For example:
#include <stdio.h>
#include <memory.h>
typedef struct {
int a;
int b;
char c[12];
} testtype_t;
int main(int argc, char* argv[]) {
testtype_t type1;
memset(&type1, 0, sizeof(testtype_t));
printf("%d, %s, %d\n", argc, argv[0], type1.a);
return 0;
}
It is not very clean, however, it seems like that for GCC maintainers, there is only one way to initialize a struct and code beauty is not on top of their list.
I'm using gcc.
I want to create a queue of my own datatype.
In the following code, when I declare struct outside main(), it works fine but it gives compile-time errors when that struct is defined inside.
#include <queue>
using namespace std;
int main()
{
struct tempPos {int a; int b;}; //....(1)
queue<tempPos> b; //works only if tempPos is defined outside main
queue<int> x; //works fine anyways
return 0;
}
Following are the errors.
test.cpp: In function ‘int main()’:
test.cpp:10:15: error: template argument for ‘template<class _Tp> class std::allocator’ uses local type ‘main()::tempPos’
test.cpp:10:15: error: trying to instantiate ‘template<class _Tp> class std::allocator’
test.cpp:10:15: error: template argument 2 is invalid
test.cpp:10:18: error: invalid type in declaration before ‘;’ token
Compilation failed.
C++ forbids using locally-defined classes with templates because they have no linkage. The standard says:
14.3.1/2: .A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argument for a template type-parameter.
I am tracking down what might be a memory leak by globally overloading operator new etc... the code to do so compiles fine under VC++, but throws problems in GCC:
15: namespace std { class bad_alloc; };
16:
17: void * operator new( size_t size ) throw ( std::bad_alloc );
18: void operator delete( void * p ) throw ();
19: void * operator new[]( size_t size ) throw ( std::bad_alloc );
20: void operator delete[]( void * p ) throw ();
The errors that are thrown are:
../zylibcpp/../zylibcpp/utility/MemoryTracker.hpp:17: error: invalid use of incomplete type ‘struct std::bad_alloc’
../zylibcpp/../zylibcpp/utility/MemoryTracker.hpp:15: error: forward declaration of ‘struct std::bad_alloc’
../zylibcpp/../zylibcpp/utility/MemoryTracker.hpp:19: error: invalid use of incomplete type ‘struct std::bad_alloc’
../zylibcpp/../zylibcpp/utility/MemoryTracker.hpp:15: error: forward declaration of ‘struct std::bad_alloc’
What is going on here ?
The type in the exception specification should be complete. Try including the <memory> <new> header which defines the exception class. The set of headers you include seem to merely declare it, which isn't enough.
Is this:
namespace std { class bad_alloc; };
in your own code? With a few exceptions (no pun intended) you can't declare things in the std namespace yourself. And the bad_alloc declaration
is incomplete.
The C++ standard (15.4) says that the type in a throw clause must be a complete type (so you can't just forward declare it). It works in MSVC because they break from the standard and say that throw(some_type) is equivalent to throw(...).