Given the following:
code-link
Here is the code itself for convenience (and I am not sure my link is working):
#include <iostream>
#include <vector>
#include <stdint.h>
using namespace std;
int main()
{
cout<<"Hello World";
std::vector<std::string> test_vect {"1", "2"};
long unsigned int size = static_cast<long unsigned int>(test_vect.size());
std::cout << "size: " << size << std::endl;
return 0;
}
And the following compile options: g++ file.c -Wall -Wextra "-Werror" "-Wuseless-cast"
You can see here that I am casting vector.size() to long unsigned int, this gets flagged up as a useless cast on Wandbox (my link) however the same code running on my linux box does not give a warning - but it will give me a different warning if I dont cast it.
I understand that the two unsigned long vs size_t can be different. But what I am trying to do is write some code that has no warnings with all the casting warnings set (maybe this is optamisitic when cross compiling).
So, one compiler complains that I am converting types, so I cast, but then another compiler is complaining about useless cast - so I remove the cast - and around we go :(
Is there a good approach to this so that I dont get warnings on either compilers?
I was going to just remove the -Wuseless-cast option, but I thought I would see if anyone has other ideas...
what I am trying to do is write some code that has no warnings with all the casting warnings set (maybe this is optamisitic when cross compiling)
It's optimistic when cross compiling if you have casts.
Is there a good approach to this so that I dont get warnings on either compilers?
Don't have casts. Make your variable be of type std::size_t.
I was going to just remove the -Wuseless-cast option
That's the other option.
As Lightness Races in Orbit pointed out, size_t is an option, it should have an appropriate macro to make compilers happy, if you somehow don't want to use that - making your variable auto or decltype(test_vect.size()) would be another option:
auto size = test_vect.size();
or
decltype(test_vect.size()) size = test_vect.size();
One argument that comes to mind is: Why does your size variable need to be long unsigned at all instead of std::size_t?
Just in case there is a compelling reason for that, how about (C++17):
long unsigned size;
if constexpr(sizeof(long unsigned)!=sizeof(std::size_t))
size = static_cast<long unsigned>(...);
else
size = ...;
Related
Whenever I am writing this following code, I am getting garbage(unexpected) output in some online compiler, but if I use code block then getting satisfied output. So my question is why I am getting this type of output?
for example, if I input
5 7
+ 5
- 10
- 20
+ 40
- 20
then I am getting
22 1
in the code block. But in the online compiler, it's something else.
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
int have, n, i;
int kid=0;
cin>>n>>have;
int line[n];
for(i=0;i<n;i++)
{
cin>>line[i];
if(line[i]>=0)
have+=line[i];
else
{
if(have>=abs(line[i]))
have+=line[i];
else
kid++;
}
}
cout<<have<<" "<<kid<<endl;
}
The main problem I can see in your code is this:
int line[n];
This is known as a VLA (Variable Length Array) and it is not supported in C++. It is valid in C. Most compilers still allow this behaviour due to the fact that C++ is based on C, but it is not valid C++ code. In a previous question, I found out that clang supports designated initializers, when gcc and vc++ did not. The reason is because some compilers like clang, support c99-extensions by default. My point is that just because the code compiles, it doesn't mean it's always right.
If you compile with the -pedantic argument, you will see that the compiler is warning you about this being a C99 feature. Have a look at the rextester example here. From the comments below, using -pedantic-errors in the compiler flags, will prompt an error.
If you know the size of the array before run-time, then you should use a static array int line[4];, but if you don't then you need to use a dynamic array. std::vector is essentially a dynamic array that also handles memory for you. It's easy to use and very efficient. std::vector<int> line;
You can read more about the vector container here: http://www.cplusplus.com/reference/vector/vector/
Btw, I tried your code in rextester, ideone and repl.it and I got the same results: 22 1. I think what you are witnessing it undefined behaviour.
Also, you can qualify int n with constexpr and it'll be fine.
constexr int n = 200;
int line[n]; //now it's ok.
But this again means that you know the size of the array at compile time.
This is perplexing. Using g++ 4.9.1:
int main()
{
void* r1 = __builtin_return_address(0); // fine
unsigned int foo = 0;
void* r2 = __builtin_return_address(foo); // does not compile
}
The error returned is error: invalid argument to ‘__builtin_return_address’
The documentation says that this function takes an unsigned int. I know the __builtin functions have all kinds of weirdness, and this just might be how life is, but I need to be able to step through this thing with an incrementing variable for a stack dumper I'm trying to implement. If it only accepts constant arguments, that's not really possible.
Is there a workaround or a better way?
Just make your own huge switch/case or if/else tree up to as many levels as you may need. You can use macros to make it simpler.
I have been playing around with boost variant and came across a scenario that seems problematic, but that I feel is my lack of knowledge on how properly use boost variant. Here is a little tester program I put together
main.cpp
#include <boost/variant.hpp>
#include <iostream>
#include <stdint.h>
typedef boost::variant<uint16_t, uint32_t> MyInt;
int main()
{
uint16_t regular = 11;
MyInt custom = regular;
std::cout << custom << '\n';
return 0;
}
Ok so the above works fine, but I get an error if I try to do the following:
int16_t invalid = 11;
MyInt custom = invalid; // This line causes the error.
I expected to get an error, but the error doesn't tell me where my problem actually occurred in my main, but in Boost's classes which isn't the most helpful when working in a bigger project.
I started to look into boost visitors to place the error in main, but didn't quite see how those would solve my issue here. Am I on the right track with visitors or am I missing some else?
Edit:
The real question here is invalid assignment of any type not specified in my variant (i.e. char, std::string, double, etc.) not so much converting int16_t to a uint16_t.
int16_t requires an implicit conversion for both uint16_t and uint32_t. Therefore, there is no best overload and the assignment/initialization fails to compile.
Coerce your type:
my_int = static_cast<int32_t>(int16_t_value);
I'm just wondering what the -fpermissive flag does in the g++ compiler? I am getting:
error: taking address of temporary [-fpermissive]
which I can solve by giving the -fpermissive flag to the compiler.
EDIT:
I just found what was causing the temporary address error part! I'm going to fix that part right now.
Right from the docs:
-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings.
Thus, using -fpermissive will allow some nonconforming code to compile.
Bottom line: don't use it unless you know what you are doing!
The -fpermissive flag causes the compiler to report some things that are actually errors (but are permitted by some compilers) as warnings, to permit code to compile even if it doesn't conform to the language rules. You really should fix the underlying problem. Post the smallest, compilable code sample that demonstrates the problem.
-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings.
Thus, using -fpermissive will allow some nonconforming code to compile.
When you've written something that isn't allowed by the language standard (and therefore can't really be well-defined behaviour, which is reason enough to not do it) but happens to map to some kind of executable if fed naïvely to the compiling engine, then -fpermissive will do just that instead of stopping with this error message. In some cases, the program will then behave exactly as you originally intended, but you definitely shouldn't rely on it unless you have some very special reason not to use some other solution.
If you want a real-world use case for this, try compiling a very old version of X Windows-- say, either XFree86 or XOrg from aboout 2004, right around the split-- using a "modern" (cough) version of gcc, such as 4.9.3.
You'll notice the build CFLAGS specify both "-ansi" and "-pedantic". In theory, this means, "blow up if anything even slightly violates the language spec". In practice, the 3.x series of gcc didn't catch very much of that kind of stuff, and building it with 4.9.3 will leave a smoking hole in the ground unless you set CFLAGS and BOOTSTRAPCFLAGS to "-fpermissive".
Using that flag, most of those C files will actually build, leaving you free to move on to the version-dependent wreckage the lexer will generate. =]
A common case for simply setting -fpermissive and not sweating it exists: the thoroughly-tested and working third-party library that won't compile on newer compiler versions without -fpermissive. These libraries exist, and are very likely not the application developer's problem to solve, nor in the developer's schedule budget to do it.
Set -fpermissive and move on in that case.
The general answer is that it "Downgrades some diagnostics about nonconformant code from errors to warnings."
Unfortunately, I haven't seen a specific list of things that it allows.
My main reason for posting an answer is to suggest that you avoid using it if at all possible. Instead, look at each error and see if it can be fixed. OP found and fixed what was causing their error. ("taking address of temporary" could be something like calling a function that returns a std::string object, and assigning something to the transient object's c_ptr() value.)
I was just reviewing a project that involved upgrading the version of gcc, and the developer added -fpermissive because there were suddenly a bunch of compilation errors. I noticed that one test was:
if (myPointer == '\0')
I pointed out that it really should be:
if (myPointer[0] == '\0')
The developer checked, and it turned out that every single thing flagged was a real error - some of which had been present for over 20 years.
As #cli_hlt mentioned
Bottom line: don't use it unless you know what you are doing!
It can do horrible things such that a compiler sometimes can cancel of constness of variables for std::map:
#include <map>
#include <vector>
#include <iostream>
#include <string>
struct B{
std::map<std::string, int> m_map;
std::vector<int> m_vector;
B(){
m_map["a"] = 1;
m_map["b"] = 2;
m_map["c"] = 3;
m_vector.emplace_back(1);
m_vector.emplace_back(2);
m_vector.emplace_back(3);
}
const std::map<std::string, int>& getMap() const {
return m_map;
}
const int& getMapValue(const std::string& key) const {
return m_map.at(key);
}
const std::vector<int>& getVector() const {
return m_vector;
}
const int& getVectorValue(const int& i) const {
return m_vector[i];
}
};
int main(){
B b;
auto& my_map = b.getMap(); // we get const ref here
my_map["a"] = 10; // here we can modify it
std::cout << "my_map[a]=" << my_map.at("a") << std::endl;
auto& my_map2 = b.getMap(); // here we return already modified variable
std::cout << "my_map2[a]=" << my_map2.at("a") << std::endl;
auto& my_value = b.getMapValue("b");
// my_value = 20; // compiler error
// std::cout << "my_map[b]=" << my_value << std::endl;
auto& my_vector = b.getVector();
// my_vector[0] = 10; // compiler error
// std::cout << "my_vector[0]=" << my_vector[0] << std::endl;
const int a = 10;
auto& a1 = a;
// a1 = 100; // compiler error
}
As you can see you can't guarantee the constness of the map, however, the constness of a vector or value can be preserved.
P.S. here I tested in the following compilers GCC 12.1, 9.1, 8.1, 7.1, 6.1.
However, clang does not -fpermissive flag have this and it will catch the error.
I am trying to play fancy games which have the C++ compiler synthesize hash values of constant strings at compiletime. This would let me replace the string with a single identifier, with a massive savings in code size and complexity.
For programming clarity and ease, it'd be awesome if I could examine and compute at compiletime with simple inline character strings like "Hello" which are compiletime constant pointers to compiletime constant chars.
If I can index into these at compiletime, I can make a template metaprogram to do what I want. But it is unclear if the C++ standard treats a ct-constant index of a ct-constant array as ct-constant by itself.
Asked another way,
const char v="Hello"[0];
is quite valid C++ (and C). But is the value v a compile time constant?
I already believe the answer is no, but in practice some compilers accept it without even any warning, much less error. For example, the following compiles and runs without even a single warning from Intel's C++ compiler:
#include <iostream>
const char value="Hello"[0];
template<char c> void printMe()
{
std::cout << "Template Val=" << c << std::endl;
}
int main()
{
const char v='H';
printMe<'H'>();
printMe<v>();
printMe<value>(); // The tricky and interesting case!
}
However, Microsoft's compiler will not compile at all, giving a reasonably coherent error message about using a template with an object with internal linkage.
I suspect the answer to my question is "No, you can't assume any array reference even to a constant array with a constant index is constant at compiletime". Does this mean the Intel compiler's successful execution is a bug in the Intel compiler?
It doesn't work on GCC either.
However, outside of a language-compliance viewpoint, it's nice that the compiler optimiser does treat it as a character constant, pretty much. I exploited that fact to allow preprocessor-generated character constants (by using *#foo). See http://cvs.openbsd.org/cgi-bin/query-pr-wrapper?full=yes&numbers=1652, in file hdr.h. With that macro, you could write
DECR(h, e, l, l, o)
rather than
DECR('h', 'e', 'l', 'l', 'o')
Much more readable, in my view. :-)
Good question, yes this can be done, and its fine with the standards, and it'll work on Microsoft, GCC, and Intel, problem is you have the syntax wrong :)
One second I'll cook up a sample...
Ok done, here it is. This sample is valid C++, and I've used it quite often, but indeed most programmers don't know how to get it right.
template<char* MSG>
class PrintMe
{
public:
void operator()()
{
printf(MSG);
}
};
char MyMessage[6] = "Hello"; //you can't use a char*, but a char array is statically safe and determined at compiletime
int main(int argc, char* argv[])
{
PrintMe<MyMessage> printer;
printer();
return 0;
}
The relevant difference here is the difference between a "Integral Constant Expression" and a mere compile-time constant. "3.0" is a compile-time constant. "int(3.0)" is a compile-time constant, too. But only "3" is an ICE. [See 5.19]
More details at boost.org