Brace Enclosed Initializer List? convert to vector - c++

so I have a piece of code that I am attempting to test. The code is checking that a few vectors (these are elements of structs) are equivalent to known vectors at certain points, however I am running into an issue. When I attempt to compare the vector to the known vector as follows,
assert((class1.getattr().getattr().getVec(key) == {4,3,2,2}))
I get the following error:
assertAll.cpp:105:82: error: could not convert ‘{4,3,2,2}’ from ‘<brace-enclosed initializer list>’ to ‘std::vector<int>’
the rest of the code is all correct, and the lval of the assert is definitely a vector as it should be. I am compiling with the flags, -std=c++11 -Wall -Wextra -pedantic -O in g++. Does anybody know how to fix this? Is there a way to typecast the bracket enclosed initializer list to a vector, or is there a better way to do this?

Does anybody know how to fix this? Is there a way to typecast the bracket enclosed initializer list to a vector
Interestingly, I get a completely different error on Clang 3.5 and GCC 4.9.2 when I try something similar, but you can just use the initializer list syntax to construct a vector in place (not quite typecasting, I guess):
assert((class1.getattr().getattr().getVec(key) == std::vector<int>{4,3,2,2}))
I'm not sure how to do that thing where you can run code on Coliru and such, but the following code works for me on GCC 4.9.2 using g++ -std=c++11 -Wall -pedantic
#include <cassert>
#include <vector>
std::vector<int> foo() {
return {1,2,3,4};
}
template<class T>
bool is_equal(const T& a, const T& b) {
return a == b;
}
int main()
{
assert((foo() == std::vector<int>{1,2,3,4}));
assert(is_equal(foo(), {1,2,3,4}));
assert([&](std::vector<int> v) -> bool {
return foo() == v;
}({1,2,3,4}));
}
Granted, nobody in their right mind would use a lambda like that, but as you might be able to tell from the examples, you basically just need to tell the compiler that the two sides are the same type in order to get it to convert the initializer list to a vector.

Related

Array bound set by a function of a generic

I want to set the array length to be the minimum of a constant and a generic like this:
template <int foo> struct Bar{
void my_func( int const (&my_array)[std::min(5, foo)] ) { /*...*/ }
};
This code compiles with clang++ but not g++ and I need my code to work with both. The error g++ gives is: error: array bound is not an integer constant before ']' token. How I can set the length of this array to be the minimum of foo and 5?
When I use clang++ I run into the problem that I can't get anything to bind to my_array. I want to run something like:
int main() {
static const int var[5] = {0,1,2,3,4};
Bar<5> bar;
bar.my_func(var);
}
But when I try to compile this code in clang++ I get: error: reference to type 'const int [*]' could not bind to an lvalue of type 'const int [5]'.
If I get rid of the std::min() stuff and replace it with foo the code compiles and runs fine.
Notes:
To get this code to compile you'll need to #include <algorithm> or similar to access std::min.
I don't think that this being part of a template should matter but when I try similar things with non-template function such as:
const int const_five = 5;
void new_func( int const (&my_array)[std::min(5,const_five)] ) { /*...*/ }
g++ says: error: variable or field 'new_func' declared void and clang++ says candidate function not viable: no known conversion from 'const int [5]' to 'const int [std::min(5, const_five)]' for 1st argument which both look like similar problems.
For int const (&my_array)[std::min(5, foo)] to compile, you need a version of std::min which is constexpr. It is since C++14.
Check the default value for -std of gcc and clang you use (its version-dependant). Ultimately, compile with -std=c++14.
Provided by StoryTeller, a nice working MCVE.
Keep it simple:
[foo < 5 ? foo : 5]

Compiler Error on std::sort function (GCC 4.4)

The code below sorting in Visual Studio successfully.
But, in Ubuntu GCC 4.4.7 compiler throws error. It seems it's not familiar with this type of syntax.
How shall I fix this line to make code working in GCC? (the compiler is remote. So I can't upgrade the GCC version either).
What I'm doing right here is:sorting Vector B elements regarding their fitness values
//B is a Vector of class Bird
//fitness is a double - member of Bird objects
vector<Bird> Clone = B;
sort(Clone.begin(), Clone.end(), [](Bird a, Bird b) { return a.fitness> b.fitness; });
//error: expected primary expresssion before '[' token
//error: expected primary expresssion before ']' token...
(Note: this 3 piece of lines compiling successful in MSVC but not in GCC)
my answer is
bool X_less(Bird a, Bird b) { return a.fitness > b.fitness; }
std::sort(Clone.begin(), Clone.end(), &X_less);
It seems to work. Is it a function or not? I don't know its technical name, but it seems to work. I am not much familiar with C++.
You will need to upgrade your C++ as 4.4 is too old to support Lambda. I have Gcc 4.8, but it still requires you enable c++11 that includes lambda functions, so
$ g++ -std=c++11 x.cc
compiles this fine
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;
int main()
{
vector<int> Clone;
sort(Clone.begin(), Clone.end(), [](int a, int b) { return a> b; });
}
but still gives errors without -std=c++11 option

Returning NULL pointer, invalid conversion from 'long int' to 'Object*'

My problem seems somewhat similar to Conversion from null-integer to pointer in comma list
Here is a minimal example
#include <utility>
struct Object {
double foo;
};
std::pair<Object*,int> test_function() {
typedef std::pair<Object*,int> pair_t;
return pair_t(NULL, 2);
}
// test.cc
With gcc 4.4.7, g++ -std=c++0x -c test.cc -o test.o fails with
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_pair.h:90: error: invalid conversion from \u2018long int\u2019 to \u2018Object*
It does compile if I omit -std=c++0x. Also, if I use newer versions of gcc, the compilation is fine. Is there anything wrong with the code? Should one expect such differences in gcc versions?
A later edit: I can also return pair_t((Object*)NULL, 2)
I believe the answer to your question is here:
C++ can't initialize a pointer in a pair to NULL
The NULL is represented as a long by gcc and it cannot be converted to type Object* without the explicit cast.

disable enum assignment g++ in if statement

I would like to treat assignment in an if statement as error:
#include <cstdio>
enum some {
a,
b
};
void foo(some e) {
if (e = a) {
puts("yes");
} else {
puts("no");
}
}
int main() {
foo(a);
return 0;
}
This seems like a sane thing to do, except that I'd like to have something like this too:
boost::optional<int> optionalValue;
if (const auto& value = optionalValue) {
}
-Wall gives me enum.cpp:9: warning: suggest parentheses around assignment used as truth value, but I would like to have something more specific than -Wall
You could declare e to be const. Then assignment would be an error.
Or, you can tell g++ to treat warnings as errors with -Werror. Then, coupled with the appropriate warning setting, any assignment in a if expression will be an error. You can enable only this class of warnings with -Wparentheses However, do note that sometimes it's not a mistake, but done on purpose. Which is why g++ suggests using parentheses to disambiguate from accidental assignment.
If you use a more recent version of g++ then it tells you which warning flag corresponds to which diagnostic. Using g++ 4.9.2 your code gives :
m.cc:9:14: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
This tells you that the error comes from the flag -Wparentheses, which is a subset of -Wall.
You can instruct g++ to treat all warnings as errors by using -Werror. But if you only want to treat this particular warning as an error then you can use:
-Werror=parentheses
This version of g++ does not warn for your suggested code const auto& value = optionalValue, so perhaps it's time to upgrade your compiler version.

Using clang 3.1 with initializer lists

When I compile this code:
template<typename T>
struct S {
std::vector<T> v;
S(initializer_list<T> l) : v(l) {
std::cout << "constructed with a " << l.size() << "-element list\n";
}
};
using the following command line:
clang++ -std=c++11 -stdlib=libc++ initializer_list.cpp
I get the following error.
initializer_list.cpp:12:23: error: expected ')'
S(initializer_list<T> l) : v(l) {
Does anyone know the fix if any??
Thanks in advance
You probably meant to write std::initializer_list<T>. Make sure you include <initializer_list>.
Your code sample is incomplete. It would be useful if you can provide a complete example. The problem with the code as written is that you're missing
#include <initializer_list>
#include <vector>
#include <iostream>
... and initializer_list is in namespace std, so you're also missing a std:: from your constructor declaration.
However, since you've claimed that neither of these is the issue, the most likely cause would seem to be that your C++ standard library implementation doesn't provide std::initializer_list. That would be the case if Clang is using GCC's libstdc++, and you do not have a suitably new version of that installed: you need at least version 4.4, but note that a patch is required to fix bugs in libstdc++-4.4 in order to make it work with Clang in C++11 mode, otherwise you will get errors about type_info and various other problems.
Also, you say that the diagnostic you received is this:
initializer_list.cpp:12:23: error: expected ')'
S(initializer_list<T> l) : v(l) {
^
(I've reconstructed the caret from the provided column number; it would be useful to preserve it in future questions.) For any of the above explanations, this will not be the first diagnostic which Clang produces; that would be something along the lines of:
initializer_list.cpp:12:5: error: no template named 'initializer_list'; did you mean 'std::initializer_list'?
S(initializer_list<T> l) : v(l) {
^~~~~~~~~~~~~~~~
std::initializer_list
So either you've missed out the first diagnostic from your question, or the problem is that you have declared some other (non-template) type named initializer_list in the code you omitted in your question, and that is hiding std::initializer_list. Without seeing the rest of your code or the rest of your diagnostics, it's not possible to tell which.