c++17

Constexpr if alternative

北城余情 提交于 2019-12-03 23:57:17
问题 I would like to use constexpr if to branch at compile time, but it does not seem to be supported by the latest MSVC compiler. Is there an alternative to the following?: template<typename T> void MyFunc() { if constexpr(MeetsConditions<T>::value) { FunctionA<T>(); } else { FunctionB<T>(); } } In short: Can I simulate constexpr if when it is not supported by the compiler? 回答1: One of pre-C++17 ways is to use partial template specializations, like here: template <template T, bool AorB> struct

Why allow shared_ptr<T[N]>?

家住魔仙堡 提交于 2019-12-03 23:55:46
This answer cites N4082 , which shows that the upcoming changes to std::shared_ptr will allow both T[] and T[N] variants: Unlike the unique_ptr partial specialization for arrays, both shared_ptr<T[]> and shared_ptr<T[N]> will be valid and both will result in delete[] being called on the managed array of objects. template<class Y> explicit shared_ptr(Y* p); Requires : Y shall be a complete type. The expression delete[] p , when T is an array type, or delete p , when T is not an array type, shall be well-formed, shall have well defined behavior, and shall not throw exceptions. When T is U[N] , Y

Why does including <utility> break structured bindings in GCC?

倾然丶 夕夏残阳落幕 提交于 2019-12-03 23:55:02
Consider: struct Point { int x, y; }; int main() { const auto [x, y] = Point{}; } This code compiles fine with gcc 7.1 in C++17 mode, however this one: #include <utility> struct Point { int x, y; }; int main() { const auto [x, y] = Point{}; } gives an error: bug.cpp: In function 'int main()': bug.cpp:7:16: error: 'std::tuple_size<const Point>::value' is not an integral constant expression const auto [x, y] = Point{}; ^~~~~~ What's going on here? A compiler bug, or is this how structured bindings are supposed to work? Barry This is compiler bug 78939 . Although it's a bit more complicated than

initializer_list with auto contains multiple expressions

≯℡__Kan透↙ 提交于 2019-12-03 23:44:30
Rather simple question, auto x11 {1,2,3,4}; auto x1 = {1,2,3,4}; auto x22 {1.0, 2.25, 3.5}; auto x2 = {1.0, 2.25, 3.5}; As far as I understand, there should be no difference here with respect to having = or not. However, using llvm/clang 6.0.0 (with --std=c++17), I get : main1.cpp:35:17: error: initializer for variable 'x11' with type 'auto' contains multiple expressions auto x11 {1,2,3,4}; ~~~~~~~~ ^ main1.cpp:37:20: error: initializer for variable 'x22' with type 'auto' contains multiple expressions auto x22 {1.0, 2.25, 3.5}; From Stroustroup's C++ book, page.162: auto x1 {1,2,3,4}; // x1 is

C++17 lambda capture *this

旧时模样 提交于 2019-12-03 23:33:22
C++17 will add copy capture of this object by value, with a capture specification of [*this] . How is this useful? How is it different than capturing this ? Can't this already be achieved in C++14 with [tmp = *this] ? Bonus for explaining why P0018R3 uses [=, tmp = *this] instead of [tmp = *this] in their example. If they had used [tmp = *this] , all the listed downsides of the C++14 solution would be eliminated. How is it useful? It's useful when you need a copy of *this - for example, when *this itself is no longer valid by the time the lambda is evaluated. How is it different from capturing

Is decltype(auto) for a structured binding supposed to be a reference?

落花浮王杯 提交于 2019-12-03 23:33:16
Consider an example: #include <iostream> #include <type_traits> #include <tuple> int main() { auto tup = std::make_tuple(1, 2); auto [ a, b ] = tup; decltype(auto) e = a; std::cout << std::boolalpha << std::is_reference_v<decltype(e)> << std::endl; } clang (output: false ) and gcc (output: true ) are disagreeing in this simple case. Having in mind e.g. this Q&As should the e be a reference or is it a gcc bug? Or maybe the code is ill-formed? The identifers themselves are references. From [dcl.struct.bind]/3 : Given the type T i designated by std​::​tuple_­element<i, E>​::​type , each v i is a

Do const references in structured bindings extend the lifetime of the decomposed object?

一世执手 提交于 2019-12-03 23:33:11
Does writing const auto& [a, b] = f(); guarantee extending the lifetime of the object returned from f() , or at least the objects a and b are bound to? Reading through the proposal I don't see anything obvious in the language to make me sure that it does unless it's just covered by something else. However, the following doesn't extend the lifetime of the temporary, so I don't see how it would be covered: const auto& a = std::get<0>(f()); At the top of the paper it seems to suggest that it is covered the cv-qualifiers and ref-qualifier of the decomposition declaration are applied to the

Do we still need to write the empty angle brackets when using transparent std function objects?

。_饼干妹妹 提交于 2019-12-03 23:27:45
With class template argument deduction we can write: std::less Fn; However, G++ 8.2 rejects this code: #include <algorithm> #include <vector> #include <functional> int main() { std::vector v= { 1, 3, 2, 7, 5, 4 }; std::sort(v.begin(),v.end(),std::greater()); } emitting the following error: error: cannot deduce template arguments for 'greater' from () Clang++ 7.0 and MSVC 15.8.0 compile it without warnings. Which compiler is right? GCC is wrong. There is already a bug report . [dcl.type.simple]/2 says: A type-specifier of the form typename opt nested-name-specifier opt template-name is a

What is the idiomatic C++17 standard approach to reading binary files?

你离开我真会死。 提交于 2019-12-03 22:55:06
问题 Normally I would just use C style file IO, but I'm trying a modern C++ approach, including using the C++17 specific features std::byte and std::filesystem . Reading an entire file into memory, traditional method: #include <stdio.h> #include <stdlib.h> char *readFileData(char *path) { FILE *f; struct stat fs; char *buf; stat(path, &fs); buf = (char *)malloc(fs.st_size); f = fopen(path, "rb"); fread(buf, fs.st_size, 1, f); fclose(f); return buf; } Reading an entire file into memory, modern

Intriguing assembly for comparing std::optional of primitive types

≡放荡痞女 提交于 2019-12-03 22:16:21
Valgrind picked up a flurry Conditional jump or move depends on uninitialised value(s) in one of my unit tests. Inspecting the assembly, I realized that the following code: bool operator==(MyType const& left, MyType const& right) { // ... some code ... if (left.getA() != right.getA()) { return false; } // ... some code ... return true; } Where MyType::getA() const -> std::optional<std::uint8_t> , generated the following assembly: 0x00000000004d9588 <+108>: xor eax,eax 0x00000000004d958a <+110>: cmp BYTE PTR [r14+0x1d],0x0 0x00000000004d958f <+115>: je 0x4d9597 <... function... +123> x