I have to compile program probcons but there are many errors. In readme autor writes program is compatible with gcc 4.3 but I have only 4.7.2. Is there any way to compile this old program? I don't believe that in program are errors because many bioinformatics servers are using it.
Most odd to me is this error:
Description Resource Path Location Type
expected ‘)’ before ‘size’ SafeVector.h /probcons line 27 C/C++ Problem
expected ‘)’ before ‘size’ SafeVector.h /probcons line 26 C/C++ Problem
In class SafeVector.h:
/////////////////////////////////////////////////////////////////
// SafeVector.h
//
// STL vector with array bounds checking. To enable bounds
// checking, #define ENABLE_CHECKS.
/////////////////////////////////////////////////////////////////
#ifndef SAFEVECTOR_H
#define SAFEVECTOR_H
#include <cassert>
#include <vector>
/////////////////////////////////////////////////////////////////
// SafeVector
//
// Class derived from the STL std::vector for bounds checking.
/////////////////////////////////////////////////////////////////
template<class TYPE>
class SafeVector : public std::vector<TYPE>{
public:
// miscellaneous constructors
SafeVector() : std::vector<TYPE>() {}
/*ERROR HERE*/ SafeVector(size_t size) : std::vector<TYPE>(size) {}
/*ERROR HERE*/ SafeVector(size_t size, const TYPE &value) : std::vector<TYPE>(size, value) {}
SafeVector(const SafeVector &source) : std::vector<TYPE>(source) {}
#ifdef ENABLE_CHECKS
// [] array bounds checking
TYPE &operator[](int index){
assert (index >= 0 && index < (int) size());
return std::vector<TYPE>::operator[] ((size_t) index);
}
// [] const array bounds checking
const TYPE &operator[] (int index) const {
assert (index >= 0 && index < (int) size());
return std::vector<TYPE>::operator[] ((size_t) index) ;
}
#endif
};
How it is possible that in older version of gcc wasn't need includes and std::prefix?
Try specifying the language standard for gcc. I suggest you try
-std=c++11
e.g g++ -std=c++11 -o out.exe myfile.cpp
first, I think it is most likely to compile it. If it doesn't work, try other choices.
How to add this depends on how the compilation is done, but one "quick&dirty" way is to add this is to find the makefile, find a line which specifies compiler flags variable CXXFLAGS and add that to it. Note: if it is a generated makefile, edits get overwritten if you run the generator again.
Related
I found this situation in my recent project. I wanna ask if it is designed as so, what's the underlying mechanism, and how is it useful?
Although I know the subscript in parameters list is somehow useless to compiler, but in my situation, it might be better to raise an error and stop compile.
The source code:
#include <cstdio>
template<typename Type>
class A{
public:
// passes compile, although it is not declared
void print(int data[Type::len]) { // Line 7
printf("%d\n", data[0]);
}
// error: not declared
// void print(int data[dummy]) {
// printf("%d\n", data[0]);
// }
};
// error: not declared
// void print(int data[A<double>::len]) {
// printf("%d\n", data[0]);
// }
int main() {
A<int> a;
int x[12] = { 0 };
a.print(x); // Line 23
return 0;
}
Compile command using gcc 11.3.0:
g++ -o a a.cpp -Wall -Wextra
No compile output, program prints a "0" and exits with 0.
But in msvc 19.33.31630, it raises C2825, C2510 on line 7, and C2670 on line 23.
There should be an error and that there isn't one is a known bug in GCC.
If the array bound Type::len was valid, then the type int[Type::len] in the function parameter would be rewritten to int* in the instantiation, as is always the case for array types in function parameters. So the actual value of the array bound will not matter from there on out.
However, if Type::len is not a valid constant expression with a suitable value for an array bound, then substitution should fail and the program should be ill-formed. In case of T=int, Type::len is not a valid expression at all and so it should fail to compile (or at least issue some diagnostic). This should happen already at A<int> a; (which causes implicit instantiation of A<int> including A<int>::print's declaration), even if no actual call to print is present.
It seems GCC is performing the rewriting step too early without verifying that the expression in the array bound is actually valid in the substitution.
GCC has a meta-bug report with multiple linked individual bug reports related to this here.
We are currently in the working of including the latest intel compiler into our pipeline for a C++14 project, but I cannot figure out two specific sections that include NaN comparisons in constexpr classes, one of which is featured below as a minimum (non-)working example. The code compiles just fine with g++, but fails with icpc (code and output see below). The numeric_limits are constexpr in C++14 and also reimplementing them gave the same error, but if I comment out the two lines featuring NaN, the code compiles with icpc
mwe.h
#include <cassert>
#include <limits>
#include <math.h>
inline constexpr double toRadians(const double inDegrees) noexcept {
return M_PI * inDegrees / 180;
}
template<typename T>
class ExpandedAbsoluteEqualityComparator {
private:
const T absoluteTolerance_;
public:
constexpr ExpandedAbsoluteEqualityComparator(const T absoluteTolerance)
: absoluteTolerance_(absoluteTolerance)
{
assert(
absoluteTolerance > 0
&& absoluteTolerance != std::numeric_limits<T>::infinity()
&& absoluteTolerance != std::numeric_limits<T>::quiet_NaN()
&& absoluteTolerance != std::numeric_limits<T>::signaling_NaN()
);
}
};
class SomeClass {
public:
//! 1° absolute tolerance floating point comparison helper for angle groups
static constexpr ExpandedAbsoluteEqualityComparator<const double> fpComparator {
toRadians(1.0)
};
};
mwe.cpp
#include "mwe.h"
int main() {return 0;}
compilation
g++ -pedantic -std=c++14 mwe.cpp # works (version 10.1.0)
icpc -std=c++14 mwe.cpp # fails (version icpc (ICC) 2021.4.0 20210910)
intel compilation error
In file included from mwe.cpp(1):
mwe.h(30): error: expression must have a constant value
static constexpr ExpandedAbsoluteEqualityComparator<const double> fpComparator {
^
mwe.h(18): note: floating-point values cannot be compared
assert(
^
compilation aborted for mwe.cpp (code 2)
Changing to
//&& absoluteTolerance != std::numeric_limits<T>::quiet_NaN()
//&& absoluteTolerance != std::numeric_limits<T>::signaling_NaN()
lets me compile with icpc
So still pretty sure this is an actual fault in the intel compiler.
Since I didn't want to remove the assert statement or the NaN check in the assert, the quick fix I ended up using was to replace the NaN comparison
absoluteTolerance != std::numeric_limits<T>::quiet_NaN() && absoluteTolerance != std::numeric_limits<T>::signaling_NaN()
with an equal to self comparison
absoluteTolerance == absoluteTolerance
assert is NOT on the list of things which are allowed in constexpr functions. It's a macro, so different compilers may expand it in different ways. Some of those expansions might just happen to be allowed in a constexpr function, but this is Unspecified. It is not a fault of any compiler if they chose to implement assert in a way that's incompatible with constexpr.
static_assert IS on the list of things allowed in constexpr functions.
#Holt, you are correct. Using -DNDEBUG you can get rid of the error.
Compilation command:icpc -DNDEBUG -std=c++14 mwe.cpp
You must #define NDEBUG (or use the flag -DNDEBUG) this will disable assert.
The assert statement so far is executed at run time.
I'm learning now C++ I'm reading the book Effective C++ (Scott Meyers).
In the book, there is an item about const variables, and I try to work with them.
I notice something very interesting that I what to know if it bug in C++:
(I'm working with C++98 standard)
void Test(const int i)
{
int arr[i] = {0};
for (int j = 0; i > j; ++j)
{
arr[j] = i;
}
}
This function will compile and work exactly as I want (create int array on the stack with the size of 'i'. When I remove the 'const' from 'i' it won't compile.
I try this on gcc and clang.
Edit:
link to Compiler Explorer
To catch this kind of mistake in the future the compiler flag you want for both g++ and clang++ is -pedantic. And always remember to specify your language standard or you don't know what you'll get.
$ g++ -std=c++98 -pedantic c++-vla.cpp -o c++-vla
c++-vla.cpp: In function ‘void f(size_t)’:
c++-vla.cpp:3:30: warning: ISO C++ forbids variable length array ‘g’ [-Wvla]
3 | void f(const size_t x) { int g[x]; }
| ^
$ clang++ -std=c++98 -pedantic c++-vla.cpp -o c++-vla
c++-vla.cpp:3:31: warning: variable length arrays are a C99 feature [-Wvla-extension]
void f(const size_t x) { int g[x]; }
^
1 warning generated.
First of all, const in your function signature is ignored by the compiler. So the following two are equivalent:
Test(const int i) {}
Test(int i) {}
Secondly, this isn't valid C++ regardless of whether it compiles or not:
int arr[i] = {0};
It isn't valid because i is not a compile time constant i.e., the value of i has to be known at the time of compilation.
Try on Compiler Explorer
Consider (the name of the file is hello.cpp) this code; the idea is to engineer a safe casting of numeric types without loss or overflow. (I'm porting some code from MSVC to g++).
#include <cstdint>
#include <iostream>
template<
typename T/*the desired type*/,
typename/*the source type*/ Y
> T integral_cast(const Y& y)
{
static_assert(false, "undefined integral cast");
}
// Specialisation to convert std::uint32_t to double
template<>
inline double integral_cast(const std::uint32_t& y)
{
double ret = static_cast<double>(y);
return ret;
}
int main()
{
std::uint32_t a = 20;
double f = integral_cast<double>(a); // uses the specialisation
std::cout << f;
}
When I compile with gcc 8.3 by typing g++ -o hello hello.cpp I get the error error: static assertion failed: undefined integral cast.
This means that g++ is always compiling the unused template code.
Note that MSVC compiles this (which is nice since it allows me to spot any integral cast specialisations that I haven't considered).
Clearly I'm missing something. But what?
GCC isn't really "instantiating" or "compiling" the base function template. If it was, you would have two compiled functions with the same name and parameter list. As #Raymond Chen pointed out in the comments, GCC is permitted, but not required, to raise an error for templates that don't have any valid instantiation.
For example:
template<
typename T/*the desired type*/,
typename/*the source type*/ Y
> T integral_cast(const Y& y)
{
static_assert(sizeof(Y) == 1);
};
Won't raise an error in the example you give (because it has a valid instantiation and is not instantiated).
I suspect GCC just needs to substitute the types into the base template for overload resolution, so it really just needs the declaration, not the definition.
You can get the behavior you want by using a deleted definition:
template<
typename T/*the desired type*/,
typename/*the source type*/ Y
> T integral_cast(const Y& y) = delete;
In C++, it is possible for pointer values to be compile-time constants. This is true, otherwise, non-type template parameters and constexpr won't work with pointers. However, as far as I know, addresses of functions and objects of static storage are known (at least) at link-time rather than compile-time. Following is an illustration:
main.cpp
#include <iostream>
template <int* p>
void f() { std::cout << p << '\n'; }
extern int a;
int main() {
f<&a>();
}
a.cpp
int a = 0;
I'm just wondering how the address of a could possibly be known when compiling main.cpp. I hope somebody could explain this a little to me.
In particular, consider this
template <int* p, int* pp>
constexpr std::size_t f() {
return (p + 1) == (pp + 7) ? 5 : 10;
}
int main() {
int arr[f<&a, &b>()] = {};
}
How should the storage for arr be allocated?
PLUS: This mechanism seems to be rather robust. Even when I enabled Randomized Base Address, the correct output is obtained.
The compiler doesn't need to know the value of &a at compile time any more than it needs the value of function addresses.
Think of it like this: the compiler will instantiate your function template with &a as a parameter and generate "object code" (in whatever format it uses to pass to the linker). The object code will look like (well it won't, but you get the idea):
func f__<funky_mangled_name_to_say_this_is_f_for_&a>__:
reg0 <- /* linker, pls put &std::cout here */
reg1 <- /* hey linker, stuff &a in there ok? */
call std::basic_stream::operator<<(int*) /* linker, fun addr please? */
[...]
If you instantiate f<b&>, assuming b is another global static, compiler does the same thing:
func f__<funky_mangled_name_to_say_this_is_f_for_&b>__:
reg0 <- /* linker, pls put &std::cout here */
reg1 <- /* hey linker, stuff &b in there ok? */
call std::basic_stream::operator<<(int*) /* linker, fun addr please? */
[...]
And when your code calls for calling either of those:
fun foo:
call f__<funky_mangled_name_to_say_this_is_f_for_&a>__
call f__<funky_mangled_name_to_say_this_is_f_for_&b>__
Which exact function to call is encoded in the mangled function name.
The generated code doesn't depend on the runtime value of &a or &b.
The compiler knows there will be such things at runtime (you told it so), that's all it needs. It'll let the linker fill in the blanks (or yell at you if you failed to deliver on your promise).
For your addition I'm afraid I'm not familiar enough about the constexpr rules, but the two compilers I have tell me that this function will be evaluated at runtime, which, according to them, makes the code non-conforming. (If they're wrong, then the answer above is, at least, incomplete.)
template <int* p, int* pp>
constexpr std::size_t f() {
return (p + 1) == (pp + 7) ? 5 : 10;
}
int main() {
int arr[f<&a, &b>()] = {};
}
clang 3.5 in C++14 standards conforming mode:
$ clang++ -std=c++14 -stdlib=libc++ t.cpp -pedantic
t.cpp:10:10: warning: variable length arrays are a C99 feature [-Wvla-extension]
int arr[f<&a, &b>()];
^
1 warning generated.
GCC g++ 5.1, same mode:
$ g++ -std=c++14 t.cpp -O3 -pedantic
t.cpp: In function 'int main()':
t.cpp:10:22: warning: ISO C++ forbids variable length array 'arr' [-Wvla]
int arr[f<&a, &b>()];
As far as I know, the variables of static storage and functions are stored simply as symbols/place holders in the symbol table while compiling. It is in the linking phase when the place holders are resolved.
The compiler outputs machine code keeping the placeholders intact. Then the linker replaces the placeholders of the variables / functions with their respective memory locations. So in this case too, if you just compile main.cpp without compiling a.cpp and linking with it, you are bound to face linker error, as you can see here http://codepad.org/QTdJCgle (I compiled main.cpp only)