Run the the following C++ program twice. Once with the given destructor and once with std::fesetround(value); removed from the destructor. Why do I receive different outputs? Shouldn't destructor be called after function add? I ran both versions on http://cpp.sh/ and Clang++ 6.0, and g++ 7.2.0. For g++, I also included #pragma STDC FENV_ACCESS on in the source code, nothing changed.
#include <iostream>
#include <string>
#include <cfenv>
struct raii_feround {
raii_feround() : value(std::fegetround()) { }
~raii_feround() { std::fesetround(value); }
inline void round_up () const noexcept { std::fesetround(FE_UPWARD ); }
inline void round_down() const noexcept { std::fesetround(FE_DOWNWARD); }
template<typename T>
T add(T fst, T snd) const noexcept { return fst + snd; }
private:
int value; };
float a = 1.1;
float b = 1.2;
float c = 0;
float d = 0;
int main() {
{
raii_feround raii;
raii.round_up();
c = raii.add(a, b);
}
{
raii_feround raii;
raii.round_down();
d = raii.add(a, b);
}
std::cout << c << "\n"; // Output is: 2.3
std::cout << d << "\n"; // Output is: 2.3 or 2.29999
}
Using the floating-point environment facilities requires inserting #pragma STDC FENV_ACCESS on into the source (or ensure that they default to on for the implementation you are using. (Although STDC is a C feature, the C++ standard says that these facilities are imported into C++ by the <cfenv> header.)
Doing so at cpp.sh results in “warning: ignoring #pragma STDC FENV_ACCESS [-Wunknown-pragmas]”.
Therefore, accessing and modifying the floating-point environment is not supported by the compiler at cpp.sh.
All I needed to do was to do std::cout << std::setprecision(30); before calling std::cout in the code (iomanip should be included as well).
Related
Using compiler explorer with:
#include <iostream>
#include <memory>
struct test
{
test(int i)
{
std::cout << "test::test("<<i<<")\n";
}
~test()
{
std::cout << "~test()\n";
}
};
template<>
void std::destroy_at(test* p)
{
std::cout<<"std::destroy_at<test>\n";
p->~test();
}
int
main ()
{
auto sp = std::make_shared<test>(3);
return 33;
}
Gives the expected output using C++20 with gcc x86-64 or clang x86-64:
Program returned: 33
test::test(3)
std::destroy_at<test>
~test()
But x64 msvc v19.32 gives:
Program returned: 33
test::test(3)
~test()
As if the std::destroy_at has no effect here.
Is this conforming behavior, my misunderstanding or a msvc non conformance or misconfiguration?
Specializing standard library functions is UB since C++20.
Are odr violations allowed with default gcc( g++, 5.4) options?
For e.g. following code
ODRTest.h
static int x = 0;
inline void odr_violates() {
++x;
std::cout << x << "\n";
}
void g();
void f();
ODRTest1.cpp
#include "ODRTest.h"
void g() { odr_violates();}
ODRTest2.cpp
#include "ODRTest.h"
void f() { odr_violates() ;}
main.cpp
#include "ODRTest.h"
int main() {
f();
g();
}
As x is static, the inline function odr_violates end up changing the static x defined in ODRTest1.cpp and ODRTest2.cpp. Isn't this a violation of ODR - one declaration and two definitions?
Following code also compiles
main.cpp
extern int q;
int main() {
std::cout << q << "\n";
}
ODRTest3.cpp
double q = 1.5;
q always gets printed as 0, is this usage an UB?
Is there an option in GCC that warns or errors out on these obvious ODR violations?
Thanks,
DDG
This C++ code compiles successfully with VS 2012 but crashes at runtime:
#include <iostream>
#include <functional>
void f()
{
std::cout << "f called" << std::endl;
}
int main()
{
auto get_f= []()
{
bool b = true;
return b ? f : f;
};
std::function<void()> filter(get_f()); // crash here!!!
return 0;
}
If we change get_f to this:
auto get_f= []()
{
return f;
};
then program runs without crashes.
Is it a problem with this code or compiler/std library bug?
I have not tested with newer versions of Visual Studio.
It looks to me like a problem with the standard library (or possibly compiler).
With VS 2013, it compiles and runs without a problem. If we add code to invoke the filter that runs as well:
#include <iostream>
#include <functional>
void f()
{
std::cout << "f called" << std::endl;
}
int main()
{
auto get_f= []()
{
bool b = true;
return b ? f : f;
};
std::function<void()> filter(get_f()); // crash here!!!
filter();
return 0;
}
Output: f called
The following code gives me a warning when using the Intel compiler icpc13.
#include <iostream>
template<int N>
class base
{
public:
double x[N];
};
template<int N>
class derived : public base<2*N>
{
public:
void print()
{
if (N==1)
{
std::cout << this->x[1] << std::endl;
}
else if (N==2)
{
std::cout << this->x[3] << std::endl;
}
}
};
int main(int argc, char* argv[])
{
derived<1> temp1;
derived<2> temp2;
temp1.print();
temp2.print();
}
Result: % icpc-13.1.163 main.cpp main.cpp(29): warning #175:
subscript out of range std::cout<x[3]<
during instantiation of "void derived::print() [with N=1]" at line
41
This is obviously not a danger since the if statement protects this line of code if the template argument is 1.
I know that I "should" do template specialization for such things, but there is some shared code in the real functions that make the if statements on template arguments really handy.
Question is…is this a "bad" thing to do, or is this incorrect compiler behavior? I don't get warnings with gcc, or xlc.
I chose the pragma solution. This ends up looking like this:
void print()
{
#ifdef __INTEL_COMPILER
#pragma warning push
#pragma warning disable 175
#endif
if (N==1)
{
std::cout<<this->x[1]<<std::endl;
}
else if (N==2)
{
std::cout << this->x[3] << std::endl;
}
#ifdef __INTEL_COMPILER
#pragma warning pop
#endif
}
};
From what I can tell, the push saves the warning flags before the disable, and the pop restores them.
Compilers do check code branches even they're inactive due to compile-time constants.
ICPC seems to be the only that checks the array bounds, but you could possibly run into other annoying warnings, like from Visual C++, which warns about constant conditional expressions when checking N (C4127 with warning level 4).
I definitely would take care of the warning, your mileage may vary:
disable warning with compiler option -wd175
disable warning at this specific point with vendor-dependent #pragma warning(disable: 175)
specialize the derived<>::print() method and factor out common code:
template<>
void derived<1>::print()
{
std::cout << x[1] << std::endl;
call_common();
}
template<>
void derived<2>::print()
{
std::cout << x[3] << std::endl;
call_common();
}
factor out the switch on N into its own specialized method derived<>::print_x():
template<>
void derived<1>::print_x()
{
std::cout << x[1] << std::endl;
}
template<>
void derived<2>::print_x()
{
std::cout << x[3] << std::endl;
}
template<int N>
void derived<N>::print()
{
print_x();
// ...
}
Given the following sample code:
#include <iostream>
#include <memory>
using namespace std;
struct A {
public:
A(int aa) : a(aa) {}
int a;
virtual ~A() {}
};
struct B : A {
public:
B(int aa, int bb) : A(aa), b(bb) {}
int b;
};
void f(shared_ptr<A> a){
shared_ptr<B> b = dynamic_pointer_cast<B>(a);
if (b) {
cout << b->b << endl;
} else {
cout << a->a << endl;
}
}
int main() {
auto a = make_shared<A>(3);
auto b = make_shared<B>(7, 4);
f(a);
f(b);
return 0;
}
Eclipse indicates that there is an error on the line
f(b);
saying Invalid arguments ' Candidates are: void f(std::shared_ptr<A>) '
because a shared_ptr<B> has been passed. This compiles and runs, and has output:
3
4
as expected.
The indexer and compiler have -std=c++11 specified.
The compiler also has the symbol __GXX_EXPERIMENTAL_CXX0X__ defined.
Is there any way to get rid of this error and its red squiggles in Eclipse (preferably without modifying the source)?
This has been fixed in later versions of CDT (I just tried it).
You can use a nightly build of CDT using this repository:
Go to Help, and enter the url http://download.eclipse.org/tools/cdt/builds/kepler/nightly
If you don't feel like using a nighty build, you should at least make sure you have the latest released version (at this writing it is 8.1.1), using http://download.eclipse.org/tools/cdt/releases/juno/
My full setup of eclipse with C++11 is found here:
http://scrupulousabstractions.tumblr.com/post/36441490955/eclipse-mingw-builds
I recommend you disable the Static Code Analysis plugin Codan in the settings it probably does not support C++11 yet.