C++ get(), at() and variant types

1、std::get(std::span)

template< std::size_t I, class T, std::size_t N >
constexpr T& get( std::span<T,N> s ) noexcept;

Span to get sthe first Ielement of reference.

The length of the span must have a static (i.e., N! = Std :: dynamic_extent) and Imust be in a range [0, N)an integer value. This is enforced at compile time, as opposed to operator[].

Parameter s: the span of the content to be extracted

Returns: the sfirst Ireference element.

Complexity: constant.

std::get(std::tuple)

Tuple access to specified elements
(function template)

std::get(std::pair)

(C++11)

Access pairan element
(function template)

std::get(std::variant)

(C++17)

Or a given index type (if unique type) read variantvalue, an exception is thrown when an error
std::get(std::array) Access arrayan element
.........  

Case:

#include <iostream>
#include <string>
#include <tuple>
#include <utility>
#include <array>
#include <variant>

int main()
{
    auto t = std::make_tuple(1, "Foo", 3.14);
    // 基于下标的访问
    std::cout << "(" << std::get<0>(t) << ", " << std::get<1>(t)
              << ", " << std::get<2>(t) << ")\n";
    // 基于类型的访问( C++14 起)
    std::cout << "(" << std::get<int>(t) << ", " << std::get<const char*>(t)
              << ", " << std::get<double>(t) << ")\n";
    // 注意: std::tie 和结构化绑定亦可用于分解 tuple

    auto p = std::make_pair(1, 3.14);
    std::cout << '(' << std::get<0>(p) << ", " << std::get<1>(p) << ")\n";
    std::cout << '(' << std::get<int>(p) << ", " << std::get<double>(p) << ")\n";

    std::array<int, 3> arr;
 
    // 设置值:
    std::get<0>(arr) = 1;
    std::get<1>(arr) = 2;
    std::get<2>(arr) = 3;
 
    // 获取值:
    std::cout << "(" << std::get<0>(arr) << ", " << std::get<1>(arr)
              << ", " << std::get<2>(arr) << ")\n";

    std::variant<int, float> v{12}, w;
    int i = std::get<int>(v);
    w = std::get<int>(v);
    w = std::get<0>(v); // 效果同前一行
 
    //  std::get<double>(v); // 错误: [int, float] 中无 double
    //  std::get<3>(v);      // 错误:合法的 index 值是 0 和 1
 
    try {
      std::get<float>(w); // w 含有 int ,非 float :将抛出异常
    }
    catch (std::bad_variant_access&) {} //错误时抛 std::bad_variant_access异常

    return 0;
}
输出:
(1, Foo, 3.14)
(1, Foo, 3.14)

(1, 3.14)
(1, 3.14)

(1, 2, 3)

2、at()

std::array<T,N>::at

reference at( size_type pos );

  (Until C++17)

constexpr reference at( size_type pos );

  (Since C++17)

const_reference at( size_type pos ) const;

  (Until C++14)

constexpr const_reference at( size_type pos ) const;

  (Since C++14)

Returns the specified location posin reference to the element, there are bounds checking.

Parameters: pos the position of the element to be returned

Return value: A reference to the required element.

Exception:! If (pos <size ()) that is posnot within the scope of the vessel, is thrown std :: out_of_range type of exception.

        The C++ container type overloads the operator[] symbol. The at() method has the same function as operator[]. The difference is that the introduced at() method is safer than operator[] to take elements. The C++ standard does not require operator[] to perform The reason for subscript out-of-bounds checking is for efficiency. Always forcing subscript out-of-bounds checking will increase the performance overhead of the program. The at() method is provided to make up for this feature of out-of-bounds access checking. Using operator[] to fetch elements and out-of-bounds access will cause the program to crash. It may directly report a segmentation error and it is difficult to find the problem code, while at() gets the element Exceeding the scope will throw an exception, which is easy to catch. In short, the operator[] method accesses the element efficiently, and at() accesses the element safely.

 

3、std::variant

Class template std::variantrepresents a type of security of the Commonwealth . std::variantAn instance of either retains the value of one of its optional types at any time, or has no value under error conditions (this state is difficult to achieve, see valueless_by_exception ).

And Commonwealth aggregate initialization consistent behavior, if the variant retains an object type Tvalue, directly to variantthe object represented by the assignment Trepresentation of the object. Do not allow variantto allocate additional (dynamic) memory.

variantKeeping references, arrays, or types is not allowed void. Air variantalso diseases of formula (Variant :: available STD < STD :: Monostate > instead).

variant It is allowed to keep the same type more than once, and it is possible to keep different cv limited versions of the same type.

With the Commonwealth, the default constructor variantretains its value the first option, that option is not available unless the default configuration (variant nor may default constructor this case: use the auxiliary class std :: monostate makes this variantmay default configuration).

#include <variant>
#include <string>
#include <cassert>
 
int main()
{
    std::variant<int, float> v, w;
    v = 12; // v 含 int
    int i = std::get<int>(v);
    w = std::get<int>(v);
    w = std::get<0>(v); // 与前一行效果相同
    w = v; // 与前一行效果相同
 
//  std::get<double>(v); // 错误: [int, float] 中无 double
//  std::get<3>(v);      // 错误:合法下标值为 0 与 1
 
    try {
      std::get<float>(w); // w 含 int 而非 float :将抛出
    }
    catch (const std::bad_variant_access&) {}
 
    using namespace std::literals;
 
    std::variant<std::string> x("abc"); // 转换构造函数在无歧义时起作用
    x = "def"; // 转换赋值在无歧义时亦起作用
 
    std::variant<std::string, void const*> y("abc");
    // 传递 char const * 时转换成 void const *
    assert(std::holds_alternative<void const*>(y)); // 成功
    y = "xyz"s;
    assert(std::holds_alternative<std::string>(y)); // 成功
}

 

Guess you like

Origin blog.csdn.net/sunlin972913894/article/details/102983033