Odd behaviour of g++ and clang++ with enabled optimization [duplicate] - c++

This question already has answers here:
Why full specialization of template function is not picked up from the .cpp file without declaration?
(3 answers)
Closed 4 years ago.
Here's my program:
print.hpp:
#pragma once
#include <iostream>
template<size_t p>
void print()
{
std::cout << "" << __FILE__ << "" << __LINE__ << "" << std::endl;
exit(0);
}
print.cpp:
#include "print.hpp"
template<>
void print<13>()
{
std::cout << "Unlucky." << std::endl;
}
main.cpp:
#include <iostream>
#include "print.hpp"
int main()
{
std::cout << "Started." << std::endl;
print<13>();
std::cout << "Exiting." << std::endl;
}
When I compile that with g++ main.cpp print.cpp -O0 -std=c++11 && ./a.out it works fine (output is:
Started.
Unlucky.
Exiting.
).
However, if'd I compile that with g++ main.cpp print.cpp -O1 -std=c++11 && ./a.out it would give me a segmentation fault with the output:
Started.
Unlucky.
Speicherzugriffsfehler //German for memory access error
Almost the same with clang++, without optimization it would do its job just fine
and with -O1 or higher it outputs that:
Started.
Unlucky.
./print.hpp8
Why is that?

You need to declare the template specialization in the .hpp file.
template<size_t p>
void print()
{
std::cout << "" << __FILE__ << "" << __LINE__ << "" << std::endl;
exit(0);
}
// Declare the specialization.
template<> void print<13>();
Without the declaration in the .hpp file, I get a linker error with g++ 6.4.0.
.../Local/Temp/cctCC5MK.o:print.cc:(.text+0x0): multiple definition of `void print<13ul>()'
.../Local/Temp/ccgodRUG.o:socc.cc:(.text$_Z5printILm13EEvv[_Z5printILm13EEvv]+0x0): first defined here
collect2: error: ld returned 1 exit status
I am not sure how you are able to successfully build your program without the declaration.

Related

why can I still give const value a new value

The book said I cannot change the value of const once I gave it a number, but it seems I can still give it a number even if it was given.
#include<iostream>
using namespace std;
const int fansc(100);
cout<< fansc << endl; //output:100
int fansc(20);
cout<< fansc << endl;//output:20
The C++ code you gave won't compile, and rightly so. A const variable(a) is, well, ... constant. The error is shown in the following program and transcript:
#include <iostream>
using namespace std;
int main() {
const int fansc(100);
cout << fansc << endl;
int fansc(20);
cout << fansc << endl;
}
pax> g++ --std=c++17 -Wall -Wextra -Wpedantic -o prog prog.cpp
prog.cpp: In function ‘int main()’:
prog.cpp:6:9: error: conflicting declaration ‘int fansc’
6 | int fansc(20);
| ^~~~~
prog.cpp:4:15: note: previous declaration as ‘const int fansc’
4 | const int fansc(100);
| ^~~~~
That leaves the Anaconda bit that you mention in a comment. I have little experience with that but it seems to me the only way that would work is if the second fansc definition was somehow created in a different scope to the first. In real C++ code, that would go something like:
#include <iostream>
using namespace std;
int main() {
const int fansc(100);
cout << fansc << endl;
{ // new scope here
int fansc(20);
cout << fansc << endl;
} // and ends here
cout << fansc << endl;
}
And the output of that is:
pax> g++ --std=c++17 -Wall -Wextra -Wpedantic -o prog prog.cpp && ./prog
100
20
100
(a) Yes, I know that's a self-contradiction :-)

G++ command throws "expected '(' for function-style cast or type construction"

Function foo takes a vector of strings. It's defined as
bool foo(vector<string>& input);
When I call foo with:
foo(vector<string>{"abc"});
my compiler gives the following error:
error: expected '(' for function-style cast or type construction
and points to { as the start of the error. This compiles fine in Xcode but I get the error when running the following via command line with:
g++ -o -std=c++17 main.cpp
What is wrong with my g++ syntax?
G++ Version Information:
g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.3 (clang-1103.0.32.59)
Target: x86_64-apple-darwin19.4.0
Thread model: posix
Your command line specifies that the output file ("-o") should be called "-std=c++17" – it does not say anything about the language version, so you're compiling as C++03.
Remove the "-o" or add an actual file name.
Also, note that your "g++" is an alias for clang.
I took your code and tried to compile it. For me there was rather problem with trying to pass non const value to function. I changed function argument to const and it compiled and printed without any problem.
#include <iostream>
#include <vector>
bool foo(const std::vector<std::string>& v) {
for (auto& a : v) { std::cout << a << std::endl; }
return true;
}
int main()
{
bool result = foo(std::vector<std::string> {"1", "2", "3" });
// do something with result
return 0;
}
Compiled on: https://www.onlinegdb.com/online_c++_compiler
Function foo expects for an l-value.
You are generating an instance and passing it to the function. But lifetime of the object is not enough for the pass-by-reference call.
Here is an example below; instance of class A is immediately destructed.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class A {
public:
A(int m): m(m) {
cerr << __func__ << endl;
}
~A() {
cerr << __func__ << endl;
}
int m;
};
int main() {
cerr << __func__ << endl;
A(5);
cerr << __func__ << endl;
return 0;
}
Outputs:
main
A
~A
main

undefined reference to variable template of pointer to function in clang but not gcc

#include <iostream>
static constexpr bool isSSE2 = true;
template<typename T>
static void (*fp)();
template<typename T>
static void foo_c() {
std::cout << "foo_c get called." << std::endl;
}
template<typename T>
static void foo_sse2() {
std::cout << "foo_sse2 get called." << std::endl;
}
int main() {
if (isSSE2)
fp<int> = foo_sse2<int>;
else
fp<int> = foo_c<int>;
fp<int>();
return 0;
}
I have a project that uses variable template which itself is a pointer to function. The example code above compiles and executes fine in GCC 6.3, but gives warning and error in clang 3.9.1.
$ clang++ "Source.cpp" -o "foo.exe" -std=c++14 -O2
Source.cpp:6:15: warning: variable 'fp<int>' has internal linkage but is not defined [-Wundefined-internal]
static void (*fp)();
^
Source.cpp:20:9: note: used here
fp<int> = foo_sse2<int>;
^
1 warning generated.
C:\msys64\tmp\Source-6600e8.o:(.text+0x2a): undefined reference to `fp<int>'
clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)
Any help is appreciated.
You have to initialize your fp<>() first:
template<typename T>
static void (*fp)() = nullptr;
It compiles and runs fine in Clang 4.0: sample code.
And try to always initialize your variables — it may save you from all sorts of headaches. :)

Why doesn't clang warn of dead code in templates?

When compiling with -Weverything, why would clang not flag the dead code in the template below, but flag it in the function? Note that in both cases, it flags the unused variable warning.
#include <iostream>
template <class Item> class ItemBase {
public:
bool performWork() {
int i;
std::cout << "foo" << std::endl;
return true;
std::cout << "dead code in template" << std::endl;
}
};
bool badFunc();
bool badFunc() {
int i;
std::cout << "foo" << std::endl;
return true;
std::cout << "dead code in function" << std::endl;
}
int main() {
ItemBase<float> tester;
tester.performWork();
badFunc();
}
clang output:
test.cpp:24:13: warning: unused variable 'i' [-Wunused-variable]
int i;
^
test.cpp:33:9: warning: unused variable 'i' [-Wunused-variable]
int i;
^
test.cpp:36:42: warning: code will never be executed [-Wunreachable-code]
std::cout << "dead code in function" << std::endl;
^~
3 warnings generated.
I don't see that there's any reason for that warning not being emitted (other than a bug in clang).
I'm guessing clang is being over-cautious about warnings in templates since it isn't able to tell that code will never be executed by any instantiation of the template (even though it's obvious to a human), so it just doesn't warn. But that's just an assumption.

"warning: RTTI symbol not found for class" with intel compiler

I am seeing these GDB warnings when I complied the below code with intel compiler 14.
I am using eclipse Kepler in RHEL6.5.
Code: (example from cplusplus.com)
#include <iostream>
#include <memory>
int main () {
std::shared_ptr<int> foo = std::make_shared<int> (10);
// same as:
std::shared_ptr<int> foo2 (new int(10));
auto bar = std::make_shared<int> (20);
auto baz = std::make_shared<std::pair<int,int>> (30,40);
std::cout << "*foo: " << *foo << '\n';
std::cout << "*bar: " << *bar << '\n';
std::cout << "*baz: " << baz->first << ' ' << baz->second << '\n';
return 0;
}
GDB Warning:
warning: RTTI symbol not found for class 'std::num_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >'
warning: RTTI symbol not found for class 'std::num_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >'
warning: RTTI symbol not found for class 'std::num_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >'
Build:
make -k all
Building file: ../src/test2.cpp
Invoking: Intel Intel(R) 64 C++ Compiler
icpc -g -std=c++11 -MMD -MP -MF"src/test2.d" -MT"src/test2.d" -c -o "src/test2.o" "../src/test2.cpp"
I don't see these warnings with g++ 4.72. Any issue with this warning? Thanks.