warning: use of old-style cast [-Wold-style-cast] - eigen

Ubuntu 18.04, gcc version 6.4.0 20180424 (Ubuntu 6.4.0-17ubuntu1)
The following program calling the Eigen library in the Openfoam2.3.1 (a Computational Fluid Dynamics (CFD) class library) build environment, and it is built by g ++ - 5 compiler.
OpenFOAM 2.3.1 shell environment: source \$HOME/OpenFOAM/OpenFOAM-2.3.1/etc/bashrc $FOAM_SETTINGS; export WM_CC=gcc-5; export WM_CXX=g++-5
#include <iostream>
#include <Eigen/Dense>
using namespace std;
int main()
{
cout << "hello CFD" << endl;
return 0;
}
I got this wanrning
./Eigen/src/Core/util/XprHelper.h:438:68: warning: use of old-style cast [-Wold-style-cast]
enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime),
^
./Eigen/src/Core/util/Macros.h:376:51: note: in definition of macro ‘EIGEN_SIZE_MIN_PREFER_DYNAMIC’
#define EIGEN_SIZE_MIN_PREFER_DYNAMIC(a,b) (((int)a == 0 || (int)b == 0) ? 0 \
^
./Eigen/src/Core/util/XprHelper.h:438:103: warning: use of old-style cast [-Wold-style-cast]
enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime),
^
./Eigen/src/Core/util/Macros.h:376:66: note: in definition of macro ‘EIGEN_SIZE_MIN_PREFER_DYNAMIC’
#define EIGEN_SIZE_MIN_PREFER_DYNAMIC(a,b) (((int)a == 0 || (int)b == 0) ? 0 \
^
./Eigen/src/Core/util/XprHelper.h:438:68: warning: use of old-style cast [-Wold-style-cast]
enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime),
^
when I use g++ to compile this programm, I will not get this warning.
can you help me?

Related

boost::hana::is_valid fails to compile with gcc8 (and more) and --std=c++14

I use this code with std=c++14 and gcc7.3:
#include <iostream>
#include <string>
#include <type_traits>
#include <boost/hana/assert.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/type.hpp>
namespace hana = boost::hana;
template<class T>
bool foo(T elem)
{
constexpr auto has_overload_to_string = hana::is_valid([](auto t) -> decltype(to_string(t)) {});
constexpr bool hasOverloadTo_string = has_overload_to_string(elem);
return hasOverloadTo_string;
}
int main()
{
std::string elem;
std::cin >> elem;
foo(elem);
}
And it works fine : demo
If now I use gcc10.1, I got this error: demo fail
prog.cc: In instantiation of 'bool foo(T) [with T = std::__cxx11::basic_string<char>]':
prog.cc:41:13: required from here
prog.cc:27:38: error: temporary of non-literal type 'foo<std::__cxx11::basic_string<char> >::<lambda(auto:1)>' in a constant expression
27 | [[maybe_unused]] constexpr auto has_overload_to_string =
| ^~~~~~~~~~~~~~~~~~~~~~
prog.cc:28:21: note: 'foo<std::__cxx11::basic_string<char> >::<lambda(auto:1)>' is not literal because:
28 | hana::is_valid([](auto t) -> decltype(to_string(t)) {});
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: note: 'foo<std::__cxx11::basic_string<char> >::<lambda(auto:1)>' is a closure type, which is only literal in C++17 and later
My question is : Is gcc7.3 too permissive with C++14 and is_valid works when it shouldn't or gcc8 and more add a bug with C++14 ?
The error has nothing to do with hana::is_valid, but the lambda is not valid in a constant expression in C++14.
There is already a good language lawyer answer for this here:
https://stackoverflow.com/a/32697323/800347
Clang also consistently provides an error, so it's clear that previous versions of gcc were incorrect in allowing this.
To workaround this, simply remove the constexpr qualifier to your variable declaration.

EIGEN library with MKL rvalue references warning

I am trying to the use the EIGEN library linked with the MKL library (icc version 17.0.4) with the code:
#define EIGEN_USE_MKL_ALL
#define lapack_complex_float std::complex<float>
#define lapack_complex_double std::complex<double>
#include <iostream>
#include <Eigen/Dense>
#include <Eigen/Eigenvalues>
#include <complex>
#include <Eigen/PardisoSupport>
using namespace Eigen;
using Eigen::MatrixXd;
int main()
{
int size = 3;
MatrixXd A(size,size);
A(0,0)=1.0; A(0,1)=-0.5; A(0,2)=0.2;
A(1,0)=0.7; A(1,1)=-1.3; A(1,2)=-2.0;
A(2,0)=0.7; A(2,1)=-1.3; A(2,2)=-2.0;
std::cout << A << std::endl;
VectorXd vec(3);
vec(0) = 2;
vec(1) = 3;
vec(2) = 4;
std::cout << A*vec << "\n";
std::cout << A.eigenvalues() << "\n";
}
I compile via
icc -I${MKLROOT}/include -L${MKLROOT}/lib -Wl,-rpath,${MKLROOT}/lib \
-lmkl_intel_lp64 -lmkl_sequential -lmkl_core -lpthread -lm -ldl \
-L/Users/user/eigen -I/Users/user/eigen
However I receive the error message:
/Users/user/eigen/Eigen/src/Core/DenseStorage.h(372): warning #3495: rvalue references
are a C++11 feature DenseStorage(DenseStorage&& other) EIGEN_NOEXCEPT
How to solve this warning?
Eigen seems to detect that your compiler supports rvalue references. You can either disable that by defining -DEIGEN_HAS_RVALUE_REFERENCES=0 via the command line or before including Eigen in your source by:
#define EIGEN_HAS_RVALUE_REFERENCES 0
Preferably, tell icc that it shall compile with C++11 support (I assume -std=c++11 works for icc as well).

Problems after commenting out "using namespace std;"

I'm new to C++ and I read that "using namespace std;" is considered bad practice. I used the following code to test if my compiler was c++14 compliant:
#include <iostream>
#include <string>
using namespace std;
auto add([](auto a, auto b){ return a+b ;});
auto main() -> int {cout << add("We have C","++14!"s);}
No errors. Then I started to play around with the code – as you do... when you learn something new. So I commented out using namespace std; and replaced cout with std::cout. Now the code looked like this:
#include <iostream>
#include <string>
//using namespace std;
auto add([](auto a, auto b){ return a+b ;});
auto main() -> int {std::cout << add("We have C","++14!"s);}
Build Messages:
||=== Build: Release in c++14-64 (compiler: GNU GCC Compiler) ===|
C:\CBProjects\c++14-64\c++14-64-test.cpp||In function 'int main()':|
C:\CBProjects\c++14-64\c++14-64-test.cpp|5|error: unable to find string literal operator 'operator""s' with 'const char [6]', 'long long unsigned int' arguments|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
Questions:
What causes the error in the second program?
How to avoid using namespace std in this case?
clang++ gives a good error message:
error: no matching literal operator for call to 'operator""s' with arguments of types 'const char *' and 'unsigned long', and no matching literal operator template
auto main() -> int { std::cout << add("We have C", "++14!"s); }
^
You use string literals and more precisely operator""s.
By removing using namespace std; you have to specify the namespace where the operator is defined.
With an explicit call:
int main() {
std::cout << add("We have C", std::operator""s("++14!", 5));
// Note the length of the raw character array literal is required
}
or with a using declaration:
int main() {
using std::operator""s;
std::cout << add("We have C", "++14!"s);
}

Issue with the templatized version of insertion sort

Below is the templatized version of insertion sort which results in compilation errors to perform insertion sort in place without any extra space.
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
template <typename T>
insertSort(T start, T end)
{
typename std::vector<typename std::iterator_traits<T>::value_type> TmpVec;
TmpVec tmp(std::make_move_iterator(start), std::make_move_iterator(end));
TmpVec::iterator begin = std::begin(tmp);
TmpVec::iterator end = std::end(tmp);
for(TmpVec::iterator i = begin; i != end; i++)
{
typename std::iterator_traits<T>::value_type value = *i;
TmpVec::iterator pos = i;
while (pos > start && *(pos-1) > value)
{
*pos = std::move(*(pos-1));
--pos;
}
*pos = value;
}
}
int main(int argc, char** argv) {
std::vector<double> arr = {1,5,3,2,6,3,9,8};
insertSort<double>(arr.begin(), arr.end());
for(int i=0; i<arr.size(); i++)
{
std::cout << arr[i] << " ";
}
return 0;
}
I am compiling this with the following compilation line.
g++ -std=c++11 -c -g -MMD -MP -MF "build/Debug/MinGW-Windows/main.o.d" -o build/Debug/MinGW-Windows/main.o main.cpp
This yields the following errors.
main.cpp: In function 'int insertSort(T, T)':
main.cpp:21:12: error: expected ';' before 'tmp'
TmpVec tmp(std::make_move_iterator(start), std::make_move_iterator(end));
^
main.cpp:22:5: error: 'TmpVec' is not a class, namespace, or enumeration
TmpVec::iterator begin = std::begin(tmp);
^
main.cpp:23:5: error: 'TmpVec' is not a class, namespace, or enumeration
TmpVec::iterator end = std::end(tmp);
^
main.cpp:24:9: error: 'TmpVec' is not a class, namespace, or enumeration
for(TmpVec::iterator i = begin; i != end; i++)
^
main.cpp:24:37: error: 'i' was not declared in this scope
for(TmpVec::iterator i = begin; i != end; i++)
^
main.cpp:27:9: error: 'TmpVec' is not a class, namespace, or enumeration
TmpVec::iterator pos = i;
^
main.cpp:28:16: error: 'pos' was not declared in this scope
while (pos > start && *(pos-1) > value)
^
main.cpp:33:10: error: 'pos' was not declared in this scope
*pos = value;
^
main.cpp: In function 'int main(int, char**)':
main.cpp:40:46: error: no matching function for call to 'insertSort(std::vector<double>::iterator, std::vector<double>::iterator)'
insertSort<double>(arr.begin(), arr.end());
^
main.cpp:40:46: note: candidate is:
main.cpp:18:1: note: template<class T> int insertSort(T, T)
insertSort(T start, T end)
^
main.cpp:18:1: note: template argument deduction/substitution failed:
main.cpp:40:46: note: cannot convert 'arr.std::vector<_Tp, _Alloc>::begin<double, std::allocator<double> >()' (type 'std::vector<double>::iterator {aka __gnu_cxx::__normal_iterator<double*, std::vector<double> >}') to type 'double'
insertSort<double>(arr.begin(), arr.end());
Kindly help in solving the above issue.
typename std::vector<typename std::iterator_traits<T>::value_type> TmpVec;
this states std::vector<typename std::iterator_traits<T>::value_type> is a typename. A compiler should issue a warning/error, because the typename is redundant.
It then declares a variable TmpVec of that type.
Every use after that uses TmpVec as if it was a type, not a variable.
You probably want
typedef std::vector<typename std::iterator_traits<T>::value_type> TmpVec;
I'd also advise
using tmp_iterator = typename TmpVec::iterator;
and using tmp_iterator as a type instead of TmpVec::iterator.

How to enable the _Generic keyword

I have this test source:
#include <stdio.h>
int main()
{
int x;
printf("x=%d\n", _Generic('x', int: 1, default: 0));
return 0;
}
Compiling with c++ (from GCC 4.9.2) fails:
t.cpp: In function ‘int main()’:
t.cpp:7:33: error: expected primary-expression before ‘int’
printf("x=%d\n", _Generic('x', int: 1, default: 0));
^
t.cpp:7:41: error: expected primary-expression before ‘default’
printf("x=%d\n", _Generic('x', int: 1, default: 0));
^
t.cpp:7:51: error: ‘_Generic’ was not declared in this scope
printf("x=%d\n", _Generic('x', int: 1, default: 0));
The compiler arguments are:
c++ --std=c++11 t.cpp -o t
What am I doing wrong?
_Generic is a C11 feature. It is not present in C++ (any version at least up to C++14 - I don't really expect it to be added either).
If you want to use it, you'll need to write C code, and use a compiler that supports that standard (reasonably recent versions of gcc and clang do for example, using -std=c11).
If you want to write C++, use overloading or templates instead, for example:
#include <iostream>
int foo(int) { return 1; }
int foo(char) { return 0; }
int main()
{
std::cout << "x=" << foo('x') << std::endl;
}
This prints x=0 in C++, the foo(char) overload is the best match.
Note that there's difference between C and C++ that might trick you here too: 'x' is a char in C++. It's an int in C. So if _Generic had been implemented (maybe as an extension) by your compiler, chances are you'd get different output when compiling your example as C versus compiling as C++.
Here's the C++ form (forgive me for using the using directive, I know its bad form):
#include <iostream>
using namespace std;
template< typename T> T do_something(T argument) {
// Put here what you need
}
int main()
{
int x;
cout << "x" << (x = do_something(x));
return 0;
}
_Generic is C11, you're probably using a C++ compiler when you meant to use a C compiler.

Resources