Cannot use a constant reference of experimental::optional when using clang & libstdc++ - c++

I'm taking a constant reference of an experimental::optional<> variable, but when I use operator->() on it, I have a compile error, but only when using clang++ and libstdc++.
#include <experimental/optional>
#include <iostream>
#include <vector>
int main(void)
{
std::experimental::optional<std::vector<int>> opt;
const auto &rf = opt;
opt.emplace();
opt->push_back(1);
std::cout << "opt->size() = " << opt->size()
<< " rf->size() = " << rf->size() << "\n";
return 0;
}
Running this program:
$ clang++ -W -Wall -std=c++14 -stdlib=libc++ test.cc && ./a.out
opt->size() = 1 rf->size() = 1 # OK
$ g++ -W -Wall -std=c++14 test.cc && ./a.out
opt->size() = 1 rf->size() = 1 # OK
$ clang++ -W -Wall -std=c++14 test.cc
In file included from test.cc:1:
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/experimental/optional:576:16: error: call to '__constexpr_addressof' is ambiguous
{ return __constexpr_addressof(this->_M_get()); }
^~~~~~~~~~~~~~~~~~~~~
test.cc:14:40: note: in instantiation of member function 'std::experimental::fundamentals_v1::optional<std::vector<int, std::allocator<int> > >::operator->' requested here
<< " rf->size() = " << rf->size() << "\n";
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/experimental/optional:173:20: note: candidate function [with _Tp = const std::vector<int, std::allocator<int> >, $1 = <>]
constexpr _Tp* __constexpr_addressof(_Tp& __t)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/experimental/optional:180:17: note: candidate function [with _Tp = const std::vector<int, std::allocator<int> >, $1 = <>]
inline _Tp* __constexpr_addressof(_Tp& __t)
^
1 error generated.
This error occurs whenever I use a constant reference: apparently non-constant references are OK.
I'm using Linux Mint 18 with these versions of g++/libstdc++ 5.4.0 and clang++ 3.8.0:
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ dpkg-query -s libstdc++-5-dev
...
Version: 5.4.0-6ubuntu1~16.04.4
...
$ clang++ --version
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Is this a bug in my program, libstdc++, or clang++?
Update: The problem goes away with clang 3.9.0. (As explained below by Richard Smith and Ville Voutilainen, it seems that libstdc++ is expecting the compiler to behave in a certain way that doesn't match clang 3.8.0.)

That certainly looks like a clang bug to me, because the overloads it diagnoses as ambiguous have mutually-exclusive enable_if constraints, so it shouldn't be possible that they are ambiguous.

Related

why does c++ std::min can't use a static field as its parameter when compile on O0?

same code, compile with O0, it will report an error:
//============================================================================
// Name : test.cpp
// Author :
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include <stdint.h>
using namespace std;
class foo{
static const int64_t MAX_THREAD_NUM = 10 * 1000;
public:
void test();
};
void foo::test(){
int64_t a = 100;
// int64_t tmp = MAX_THREAD_NUM;
// int64_t min = std::min(tmp, a);
int64_t min = std::min(MAX_THREAD_NUM, a);
cout << min << endl; // prints !!!Hello World!!!
}
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/test.d" -MT"src/test.o" -o "src/test.o" "../src/test.cpp"
g++ -o "test" ./src/test.o
./src/test.o: In function `foo::test()':
/home/foo/eclipse-workspace/test/Debug/../src/test.cpp:27: undefined reference to `foo::MAX_THREAD_NUM'
collect2: error: ld returned 1 exit status
/home/foo/eclipse-workspace/test/Debug/../src/test.cpp:27: undefined reference to `foo::MAX_THREAD_NUM'
but with O2 flag, it can compile succeed.
g++ -O2 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/test.d" -MT"src/test.o" -o "src/test.o" "../src/test.cpp"
g++ -o "test" ./src/test.o
g++ version:
g++ (Ubuntu 4.8.5-4ubuntu8) 4.8.5
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
Program is ill-formed no diagnostic required (NDR) as you break One Definition Rule (ODR) by not providing definition of ODR-used symbol (std::min takes its argument by reference).
The optimizer removes that unused code and lets you think it is correct.
As pointed out by #dfri, compiler inlines MAX_THREAD_NUM. If we change it to inline static const int64_t MAX_THREAD_NUM = 10 * 1000;, it will compile fine on O0. Otherwise, declare but define the variable outside of the class, or mark it constexpr instead of const. Using a static const integral member needs definition if it's used where a non-const integral is needed.
class foo {
static const int64_t MAX_THREAD_NUM;
...
};
const int64_t foo::MAX_THREAD_NUM = 10 * 1000;

Compilation Error: "‘function’ in namespace ‘std’ does not name a template type"

I'm trying to sniff my network traffic using libtins library. So I downloaded the tar.gz library and I finished all the library compilation steps mentioned in the manual one by one successfully.
Now, I'm trying to compile my first sample program:
1 #include <iostream>
2 #include <tins/tins.h>
3
4 using namespace Tins;
5
6 bool callback(const PDU &pdu) {
7 const IP &ip = pdu.rfind_pdu<IP>(); // Find the IP layer
8 const TCP &tcp = pdu.rfind_pdu<TCP>(); // Find the TCP layer
9 std::cout << ip.src_addr() << ':' << tcp.sport() << " -> "
10 << ip.dst_addr() << ':' << tcp.dport() << std::endl;
11 return true;
12 }
13
14 int main() {
15 Sniffer("eth0").sniff_loop(callback);
16 }
When I want to compile it, I face the following errors:
me#me-MS-7693:~/Desktop/Workspace/cpp_libtins$ g++ main.cpp -ltins
In file included from /usr/local/include/tins/tins.h:60:0,
from main.cpp:2:
/usr/local/include/tins/crypto.h:297:18: error: ‘function’ in namespace ‘std’ does not name a template type
typedef std::function<void(const std::string&,
^
/usr/local/include/tins/crypto.h:308:18: error: ‘function’ in namespace ‘std’ does not name a template type
typedef std::function<void(const std::string&,
^
/usr/local/include/tins/crypto.h:401:44: error: ‘handshake_captured_callback_type’ does not name a type
void handshake_captured_callback(const handshake_captured_callback_type& callback);
^
/usr/local/include/tins/crypto.h:412:34: error: ‘ap_found_callback_type’ does not name a type
void ap_found_callback(const ap_found_callback_type& callback);
^
/usr/local/include/tins/crypto.h:445:9: error: ‘handshake_captured_callback_type’ does not name a type
handshake_captured_callback_type handshake_captured_callback_;
^
/usr/local/include/tins/crypto.h:446:9: error: ‘ap_found_callback_type’ does not name a type
ap_found_callback_type ap_found_callback_;
^
me#me-MS-7693:~/Desktop/Workspace/cpp_libtins$
What is wrong?
My compiler version:
me#me-MS-7693:~/Desktop/Workspace/cpp_libtins$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
me#me-MS-7693:~/Desktop/Workspace/cpp_libtins$
Since your GCC is older than 6.0, you need to pass the -std=c++11 switch, otherwise it is in C++03 mode. C++03 did not have std::function.

max_element with lambda: how to compile?

I am learning some new C++ features and couldn't get the following code compiled.
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> numbers;
numbers.push_back(1);
numbers.push_back(5);
numbers.push_back(3);
numbers.push_back(9);
numbers.push_back(10);
numbers.push_back(8);
std::cout << std::max_element(numbers.begin(), numbers.end(), [](int a, int b) { return a < b;}) << std::endl;
return 0;
}
My gcc version:
$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
The output when I try to compile:
$ g++ test_max_element.C
test_max_element.C: In function ‘int main()’:
test_max_element.C:15:99: warning: lambda expressions only available with -std=c++0x or -std=gnu++0x [enabled by default]
test_max_element.C:15:100: error: no matching function for call to ‘max_element(std::vector<int>::iterator, std::vector<int>::iterator, main()::<lambda(int, int)>)’
test_max_element.C:15:100: note: candidates are:
/usr/include/c++/4.6/bits/stl_algo.h:6229:5: note: template<class _FIter> _FIter std::max_element(_FIter, _FIter)
/usr/include/c++/4.6/bits/stl_algo.h:6257:5: note: template<class _FIter, class _Compare> _FIter std::max_element(_FIter, _FIter, _Compare)
How can I fix this compilation error?
I have 2 hints here.
Syntax Error
std::cout << *std::max_element(numbers.begin(), numbers.end(), [](int a, int b) { return a < b;}) << std::endl;
Note the * operator. You need it because max_element returns an iterator, so in order to print the value you have to deference it.
Obsolete Compiler Version
You're trying to using a modern C++ features with a too old compiler. I suggest you to upgrade it.
Anyway you can use the current compiler's version you have just add the flag -std=c++0x to the compiler command. But seeing from your question probabily the flag is enable by default.

"error: no viable conversion from tuple..." using make_tuple

I'm trying to have a function return std::tuple<Qstring, int>, but I'm getting this compiler error:
std::tuple<QString, int> foo()
{
auto fst = getFst();
auto snd = getSnd();
return std::make_tuple(fst, snd);
}
`error: no viable conversion from 'tuple<[...], typename __make_tuple_return::type>' to 'tuple<[...], int>'``
What am I doing wrong?
There's nothing wrong with this code. It compiles without any issues.
$ cat t.C
#include <QString>
#include <tuple>
std::tuple<QString, int> foo()
{
QString fst = QString("fst");
int snd = 2;
return std::make_tuple(fst, snd);
}
$ g++ -std=c++11 -I/usr/include/QtCore -c -o t.o t.C
$ g++ --version
g++ (GCC) 5.3.1 20151207 (Red Hat 5.3.1-2)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

error: ‘unique_ptr’ is not a member of ‘std’

I guess it's pretty self explanatory - I can't seem to use C++11 features, even though I think I have everything set up properly - which likely means that I don't.
Here's my code:
#include <cstdlib>
#include <iostream>
class Object {
private:
int value;
public:
Object(int val) {
value = val;
}
int get_val() {
return value;
}
void set_val(int val) {
value = val;
}
};
int main() {
Object *obj = new Object(3);
std::unique_ptr<Object> smart_obj(new Object(5));
std::cout << obj->get_val() << std::endl;
return 0;
}
Here's my version of g++:
ubuntu#ubuntu:~/Desktop$ g++ --version
g++ (Ubuntu/Linaro 4.7.3-2ubuntu1~12.04) 4.7.3
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Here's how I'm compiling the code:
ubuntu#ubuntu:~/Desktop$ g++ main.cpp -o run --std=c++11
main.cpp: In function ‘int main()’:
main.cpp:25:2: error: ‘unique_ptr’ is not a member of ‘std’
main.cpp:25:24: error: expected primary-expression before ‘>’ token
main.cpp:25:49: error: ‘smart_obj’ was not declared in this scope
Note that I've tried both -std=c++11 and -std=c++0x to no avail.
I'm running Ubuntu 12.04 LTS from a flash drive on an Intel x64 machine.
You need to include header where unique_ptr and shared_ptr are defined
#include <memory>
As you already knew that you need to compile with c++11 flag
g++ main.cpp -o run -std=c++11
// ^
So here what I learned in 2020 - memory.h is at /usr/include AND in /usr/include/c++/4.8.5 and you need the second to be found before the first.
In Eclipse set the order using Project->Properties->Path and Symbols->Includes->Add... path if needed and set first
You need to include #include that will solve the problem, at least on my ubunto linux machine