C + + 17 new features
- preface
- If Statements with Initializer
- Constexpr if
- The inline variable
- Nested namespaces
- Property specifier
- [[FallThrough]] Standard properties
- [[maybe_unused]] Standard attribute
- [[nodiscard]] Standard attribute
- [[deprecated]] Standard attribute
- [[noretrun]] Standard attributes
- string_view
- filesystem
- any
- optional
- variant
- execution
- Refer to the link
preface
The previous C++ project used C++14 standard, and considering The Times, C++20 has been basically confirmed. However, since the built-in GCC on the current Linux (uos) does not fully support C++20, so we temporarily consider the new C++17 standard in the new project. And write a complete brief document of the new features that a project might use in C++17
visual studio 2019
Compilation parameters need to be added/std:c++17
If Statements with Initializer
If statement with initializer
example
std::map<std::string, int> map;
map["nihao"] = 1;
map["shijie"] = 2;
if (auto ret = map.begin(a); ret ! = map.end()) {
std::cout << ret->first << ":" << ret->second;
}
Copy the code
Constexpr if
In a CONSTEXPr IF statement, the value of a condition must be a converted constant expression that can be converted to bool contextually. If the value is true, the false branch statement (if present) is discarded, otherwise the true branch statement is discarded.
Often difficult to use for business writing, this is especially useful in template metaprogramming
example
template <typename T>
void TestConstexprIf(T value) {
if constexpr (std::is_integral_v<T>)
std::cout << "is integral" << std::endl;
else
static_assert(false."T must be an integer.");
}
Copy the code
The inline variable
Inline variables are used to resolve a problem where a global variable is used multiple times after being defined in a header file resulting in a symbol redefinition error
The wrong case
// test.h header file
int test = 10;
// test1.cpp
void Function1(a) {
test = 20;
}
// test2.cpp
void Function(a) {
test = 30;
}
// the above code compilation will generate a redefinition error. Prior to c++17, the solution was to use extern to export global variables
// Solution
// test.h header file
extern int test;
// test.cpp
int test = 10;
Copy the code
After C++17, inline variables were introduced to allow global variables to declare definitions directly in header files
example
inline int test = 10;
Copy the code
Nested namespaces
example
namespace test::test2 {
int i = 0;
}
std::cout << test::test2::i << std::endl;
Copy the code
Property specifier
Attributes for various implementation-defined language extensions (such as GNU and IBM’s __attribute__((…)) ), Microsoft’s language extensions __declSpec (), etc.) provide a unified syntax.
[[FallThrough]] Standard properties
Indicates that a drop from the previous label is intentional, and a compiler that warns when a drop occurs should not diagnose it.
Under the C++17 standard, there is the following code
switch (device.status())
{
case sleep:
device.wake(a);// fall thru
case ready:
device.run(a);break;
case bad:
handle_error(a);break;
}
Copy the code
C++17 could be written like this
switch (device.status())
{
case sleep:
device.wake(a); [[fallthrough]];case ready:
device.run(a);break;
case bad:
handle_error(a);break;
}
Copy the code
The previous code compiler will tell you that there is no break warning, but the fallthrough property in c++17 will eliminate this warning
[[maybe_unused]] Standard attribute
Can be used to eliminate warnings from unused function and variable compilers
example
[[maybe_unused]] bool testUnusedVariable = true;
[[maybe_unused]]
void TestUnusedFunction(a) {}Copy the code
[[nodiscard]] Standard attribute
If the return value of one of your functions is particularly important, you can add this property, and a warning will be generated if the function user does not use the return value during recompilation
example
[[nodiscard]] bool TestNodiscard(a) {
return true;
}
Copy the code
[[deprecated]] Standard attribute
Hints allow the use of names or entities that declare this property, but are discouraged for some reason, generally for functions that are about to be deprecated, but are still used by older users
example
// This is not a warning but an error in vs.
[[deprecated("test deprecated")]] bool TestDeprecated(a) {
return true;
}
Copy the code
[[noretrun]] Standard attributes
Tell the function that it does not return a value
example
[[noreturn]] void TestNoreturn(a) {}Copy the code
string_view
String_view is a read-only string compared to string. The space and time cost of the assignment of string_view is much higher than that of string. Assignment of string_view is particularly like assignment of a pointer, and string_view is generally more appropriate in the following situations
exampel
/ / constant string
const std::string = "hello world";
// string_view is more appropriate
const string_view = "hello world";
// Function arguments
void Function1(const std::string& arg1) {}// string_view is more appropriate
void Function1(string_view arg1) {}Copy the code
filesystem
The experiment/filesystem was used until C++17, when filesystem was officially included in the C++ standard library. Since most people are familiar with filesystem, this is a brief introduction
example
std::filesystem::path path("testpath");
if (std::filesystem::exists(path)) {
/ / there
} else {
/ / does not exist
}
Copy the code
any
Any is a type-safe container that can be used with a single value of any type. If you’ve seen Boost before, you’re probably familiar with the Any class
example
std::any Int = 69;
std::any Double = 69.123;
std::any String = std::string_view("Hello");
std::cout << Int.type().name() << std::endl;
std::cout << Double.type().name() << std::endl;
std::cout << Double.type().name() << std::endl;
std::vector<std::any> anys = { Int, Double, String };
std::cout << std::any_cast<int>(Int) << std::endl;
std::cout << std::any_cast<double>(Double) << std::endl;
std::cout << std::any_cast<std::string_view>(String) << std::endl;
// has_value: indicates whether there is a value
std::any a = 1;
if (a.has_value()) {
std::cout << a.type().name() << std::endl;// i
}
// reset: Clears the container
a.reset(a);if (a.has_value()) {
std::cout << "no value\n";// no value
}
Copy the code
optional
If you’re familiar with Boost, you’re probably familiar with optional. It’s most commonly used in cases where you’re returning a string or int that is very implicit. STD :: Optional can help you with this
example
[[nodiscard]]
std::optional<int> TestOptional(a) {
// Before we might have used return-1 to indicate an error, but now st::optional doesn't need to be too implicit
if (true) {
return 9999;
} else {
return std::nullopt;
}
}
[[nodiscard]]
std::optional<std::string> TestOptional2(a) {
// Before we might have used return-1 to indicate an error, but now st::optional doesn't need to be too implicit
if (true) {
return "helloworld";
} else {
returnstd::nullopt; }}// optional
auto result = TestOptional(a);if (result.has_value()) {
// If there is a value, it indicates success
} else {
// result has no value indicating failure
}
// This value_OR is used when the return value of TestOptional is nullopt
auto ret = TestOptional2().value_or("");
Copy the code
variant
Variant is used to represent a type-safe union, and an instance of variant either retains a value of one of its optional types at any time or has no value in the case of an error. Variant does not allow you to hold references, arrays, or types of void. A null variant can use STD :: Variant < STD ::monostate>
// variant
struct SystemProxyConfig {
bool isService;
};
struct CustomProxyConfig {
bool isFile;
std::string pathOrContent;
};
std::variant<SystemProxyConfig, CustomProxyConfig> config;
/ / config = CustomProxyConfig {false, "http://192.168.21.161/spiderweb.pac"};
config = SystemProxyConfig{ false };
if (std::get_if<CustomProxyConfig>(&config)) {
// Type succeeded
CustomProxyConfig customConfig = std::get<CustomProxyConfig>(config);
} else {
// Type failed
SystemProxyConfig systemProxyConfig = std::get<SystemProxyConfig>(config);
int i = 0;
}
Copy the code
execution
Execution provides a set of execution strategies for the C++STL algorithm library, currently supporting:
sequenced_policy
(Sequential execution of policies)parallel_policy
(Parallel execution strategy)parallel_unsequenced_policy
(Parallel and out-of-order execution of policies)unsequenced_policy
(Execute policies out of order)
example
std::vector<int> testExecution{ 1.2.3.4.5.8.19.20 ,30.40.50.0.102.40.10.30.20.1000.32.31.34.45};
auto it1 = std::find(std::execution::seq, testExecution.begin(), testExecution.end(), 5);
auto it2 = std::find(std::execution::par, testExecution.begin(), testExecution.end(), 5);
auto it3 = std::find(std::execution::par_unseq, testExecution.begin(), testExecution.end(), 5);
Copy the code
Refer to the link
cppreference.com
Fallthrough properties