I want to use c++1z in MacOS10.14.4, like this g++ -std=c++1z test.cpp -o test. But the clang can't compile the code.
The error as follows.
In file included from test.cpp:3:
/Library/Developer/CommandLineTools/usr/include/c++/v1/any:599:5: error: static_assert failed due to requirement 'is_constructible<basic_string<char> &&, _RawValueType
&>::value' "ValueType is required to be an lvalue reference or a CopyConstructible type"
static_assert(is_constructible<_ValueType, _RawValueType &>::value,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:29:19: note: in instantiation of function template specialization 'std::__1::any_cast<std::__1::basic_string<char> &&>' requested here
auto b = std::any_cast<std::string&&>(a); //< rvalue reference (no need for std::move)
^
1 error generated.
But the same code can work on Linux. The code as follows.
#include <string>
#include <iostream>
#include <any>
int main()
{
// simple example
auto a = std::any(12);
std::cout << std::any_cast<int>(a) << '\n';
try {
std::cout << std::any_cast<std::string>(a) << '\n';
}
catch(const std::bad_any_cast& e) {
std::cout << e.what() << '\n';
}
// advanced example
a = std::string("hello");
auto& ra = std::any_cast<std::string&>(a); //< reference
ra[1] = 'o';
std::cout << "a: " << std::any_cast<const std::string&>(a) << '\n'; //< const reference
auto b = std::any_cast<std::string&&>(a); //< rvalue reference (no need for std::move)
// Note, 'b' is a move-constructed std::string, 'a' is now empty
std::cout << "a: " << *std::any_cast<std::string>(&a) //< pointer
<< "b: " << b << '\n';
}
clang version: Apple LLVM version 10.0.1 (clang-1001.0.46.4)
And I use the gcc to compile this code, but didn't work either.
This seems to be from https://developercommunity.visualstudio.com/content/problem/200281/stdany-cast-static-assert-error-because-of-is-cons.html, which has an answer from Microsoft. The answer there was that this was a defect LWG 2768, so the fix may not have been implemented in older implementations of the standard library. For example, this compiles in clang 6.0.0 and gcc 7.4, but not clang 7.0.0 and gcc 8.1.
The reason is that you can't take an rvalue reference of an lvalue any. Fix this by either taking an lvalue reference and moving that or taking an rvalue reference of a moved any:
std::move(std::any_cast<std::string&>(a));
std::any_cast<std::string&&>(std::move(a));
Related
#include <iostream>
int main() {
bool b = true;
std::cout << std::is_same<decltype(!(!b)), bool>::value << "\n";
auto bb = (!(!b));
std::cout << std::is_same<decltype(bb), bool>::value << "\n";
}
The above code has different results using different compilers.
Is this a compiler bug or am I missing something?
clang 1 1 (https://godbolt.org/z/s43T55rxq)
msvc 1 1 (https://godbolt.org/z/YnKfKh41q)
gcc 0 1 (https://godbolt.org/z/91xdfv93c)
This is a gcc bug. The problem is that gcc incorrectly treats the expression !(!b) as an lvalue instead of rvalue. You can confirm this here. As you'll see in the above linked demo, the output gcc gives is lvalue instead of prvalue.
The bug has been reported as:
GCC treats rvalue as an lvalue
Which of the following C++ lambdas/statements are supposed to work according to the latest C++ specification?
Context in case this is relevant: see here.
I tested the following code snippets with -std=c++17 on Fedora 33 with clang 11.0.0 and gcc 10.2.1.
Update: Replace __PRETTY_FUNCTION__ with __func__ for standard compliance. The same behavior can be observed.
Update2: Example using const char * s = __func__ as default argument to verify that it should be valid within a function scope (thanks to #BenVoigt).
1. LLVM __func__ within lambda default argument
void clang() {
[](const char* c = __func__) {std::cout << c << std::endl;}();
}
Expected behavior (CLANG):
Print out clang\n (void clang() for __PRETTY_FUNCTION__)
Observed behavior (CLANG):
Compiler warning: warning: predefined identifier is only valid inside function [-Wpredefined-identifier-outside-function]
Print out \n (top level() for __PRETTY_FUNCTION__)
2. GCC ignores statements
template <typename L>
constexpr std::string_view methodName(L l) { return l(); }
#define __METHOD_NAME__ (\
__func__, /* needed for pointer to work */ \
methodName([](const char* c = __func__) {return std::string_view(c);}) \
)
void gcc1() {
std::cout << [](const char* c = __func__) { return c; }() << std::endl; // GCC: This statement doesn't do anything
std::cout << [](const char* c = __func__) { return c; }("gcc") << std::endl;
std::cout << __METHOD_NAME__ << std::endl; // GCC: This statement somehow conflicts with the statements above
}
void gcc2() {
std::cout << __METHOD_NAME__ << std::endl; // GCC: This statement itself works
}
Expected output (GCC):
gcc1
gcc
gcc1
gcc2
Observed output (GCC):
gcc
gcc2
3. GCC Compile error
void gcc3() {
std::string_view s = [](const char* c = __func__) { return std::string_view(c); }();
std::cout << s << std::endl;
}
Expected behavior (GCC): Compiles without problems.
Observed behavior (GCC): error: internal compiler error: in finish_expr_stmt
[class.local] The local class is in the scope of the enclosing scope, and has the same access to names outside the function as does the enclosing function. [Note: A declaration in a local class cannot odr-use (6.2) a local entity from an enclosing scope. — end note]
A lambda is a local class, and as such it cannot use variables from the enclosing scope (e.g. __func__) other than in its capture clause.
I assume C++ Compound type alterations support should be enabled in clang++ by -std=c++11 switch. But I'm unable to compile this code using clang:
#include <iostream>
#include <type_traits>
enum class A {a,b,c};
enum B : short {x,y,z};
int main() {
typedef std::underlying_type<A>::type A_under; // int
typedef std::underlying_type<B>::type B_under; // short
std::cout << std::boolalpha;
std::cout << "typedefs of int:" << std::endl;
std::cout << "A_under: " << std::is_same<int,A_under>::value << std::endl;
std::cout << "B_under: " << std::is_same<int,B_under>::value << std::endl;
return 0;
}
I get this error:
$ clang++ underlyingtype.cpp -std=c++11
underlyingtype.cpp:10:16: error: no type named 'underlying_type' in namespace 'std'
typedef std::underlying_type<A>::type A_under; // int
Any idea why this is happening?
Further information:
lashgar#fengdu:~/code$ clang++ --version
clang version 3.8.0 (http://llvm.org/git/clang.git 1ad799453a2e54cfded555a03fd58dbd102c5f62) (http://llvm.org/git/llvm.git af5ff60200812e518c72a022fb4c66b9a5f0116a)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/lashgar/opt/llvm/bin
Here's a link to an online compiler with libstdc++ 4.6.4 that reproduces this error.
Just make sure to get the version of your Standard Library. libstdc++ 4.7 and higher or libc++ 3.0 and higher should work correctly.
I'm trying to get Intel C++ 14.0.2 compiler to use the C++11 options. I've got this really simple code (which I simplified from: cplusplus.com):
// shared_ptr constructor example
#include <iostream>
#include <memory>
struct C {int* data;};
int main () {
std::shared_ptr<int> p1;
std::cout << "use_count:\n";
std::cout << "p1: " << p1.use_count() << '\n';
return 0;
}
I tried to compile this with the Intel C++ 14.0.2 compiler but I just get these errors:
$ icpc --std=c++11 test.cpp
test.cpp(8): error: namespace "std" has no member "shared_ptr"
std::shared_ptr<int> p1;
^
test.cpp(8): error: type name is not allowed
std::shared_ptr<int> p1;
^
test.cpp(8): error: identifier "p1" is undefined
std::shared_ptr<int> p1;
^
compilation aborted for test.cpp (code 2)
(I've also tried using -std=c++11, but got the same errors.) Am I using the shared_ptr wrong? Am I invoking the compiler wrong? This seems to be about as simple an example as I can come up with to illustrate this problem.
shared_ptr isn't listed as one of the supported features for version 14.0 in Intel's list of supported features:
http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler
I have error: ‘class std::queue<int>’ has no member named ‘swap’ while compiling following code
#include <iostream> // std::cout
#include <queue> // std::queue
int main ()
{
std::queue<int> foo,bar;
foo.push (10); foo.push(20); foo.push(30);
bar.push (111); bar.push(222);
foo.swap(bar);
std::cout << "size of foo: " << foo.size() << '\n';
std::cout << "size of bar: " << bar.size() << '\n';
return 0;
}
I'm using g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 for compiling this code,can anyone have a idea for this error?
Use:
std::swap(foo, bar);
It appear that since c++11, you have std::queue::swap
http://www.cplusplus.com/reference/queue/queue/swap-free/
g++ 4.6 appears to not accept -std=c++11, so you must upgrade your compiler for this method to work.
[edit]
g++ 4.6 accepts -std=c++0x to enable c++11