C++ std::holds_alternative, std::get, std::variant application examples (219)

Introduction: CSDN blog expert, focusing on Android/Linux System, share multi-mic voice solutions, audio and video, codec and other technologies, and grow with everyone!

Quality Column:Audio Engineer Advanced Series[Original information is being updated continuously… ]

Life motto: There are never shortcuts in life, only actions It is the only cure for fear and laziness.


For more original works, welcome to follow: Android System Siege Lion

Welcome to follow Android System Siege Lion

1. Preface

The purpose of this article: Understand the usage of std::get in C++.

1. In C++, std::holds_alternative is a template function used to check whether the given std::variant object contains a value of the specified type. It returns a bool value indicating whether the given type exists in std::variant.
2. In C++, std::get is used to obtain from types such as std::tuple and std::variant Function template for values. It accepts an index as a parameter and returns the value at the corresponding position.
3. In C++, std::variant is a general polymorphic type introduced by the C++17 standard. It can store different types in a single variable. The purpose of std::variant is to provide a type-safe way to handle multiple possible types.

std::variant can store one of a set of predefined types, called an “optional type list”. When creating a std::variant object, you need to specify a list of optional types. This way, you can store any of these types in the std::variant object.

When using std::variant, you can use std::get to get the value stored in std::variant, or use std::visit to perform polymorphic processing on the value in std::variant. In addition, you can also use std::holds_alternative to check whether a specific type is stored in std::variant.

2. Application examples

<1>.v1.0: std::variant application example

#include <variant>
#include <iostream>
#include <string>

int main() {<!-- -->
    std::variant<int, std::string> var;

    var = 42; // Store a value of type int
    std::cout << std::get<int>(var) << std::endl; // Output: 42

    var = "Hello"; // Store a value of type std::string
    std::cout << std::get<std::string>(var) << std::endl; // Output: Hello

    return 0;
}

<2>.v2.0: std::holds_alternative usage

#include <iostream>
#include <variant>
#include <string>

int main() {<!-- -->
    std::variant<int, double, std::string> myVariant = "Hello";

    // Use std::holds_alternative to check whether the specified type exists in the variant
    bool isInt = std::holds_alternative<int>(myVariant);
    bool isDouble = std::holds_alternative<double>(myVariant);
    bool isString = std::holds_alternative<std::string>(myVariant);

    std::cout << "isInt: " << isInt << std::endl; // Output: isInt: 0
    std::cout << "isDouble: " << isDouble << std::endl; // Output: isDouble: 0
    std::cout << "isString: " << isString << std::endl; // Output: isString: 1

    return 0;
}

<3>.v3.0: For std::tuple, usage of std::get.

#include <iostream>
#include <tuple>

int main() {<!-- -->
  std::tuple<int, std::string, double> myTuple(42, "Hello", 3.14);

  // Use std::get to get the value in the tuple
  int intValue = std::get<0>(myTuple);
  std::string stringValue = std::get<1>(myTuple);
  double doubleValue = std::get<2>(myTuple);

  std::cout << intValue << std::endl; // Output: 42
  std::cout << stringValue << std::endl; // Output: "Hello"
  std::cout << doubleValue << std::endl; // Output: 3.14

  return 0;
}

<4>.v4.0: Usage of std::get for std::variant.

#include <iostream>
#include <variant>
#include <string>

int main() {<!-- -->
  std::variant<int, std::string, double> myVariant = 42;

  // Use std::get to get the value stored in the variant
  int intValue = std::get<int>(myVariant);
  std::cout << intValue << std::endl; // Output: 42

  // Trying to use std::get to get a mismatched type will throw a std::bad_variant_access exception.
  try {<!-- -->
    std::string stringValue = std::get<std::string>(myVariant);
  } catch(const std::bad_variant_access & amp; e) {<!-- -->
    std::cout << "Error: " << e.what() << std::endl; // Output: Error: std::bad_variant_access
  }

  return 0;
}

<5>.v5.0: std::holds_alternative, std::variant instances

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

using namespace std;

using Elem = std::variant<std::monostate, int32_t, int64_t, double, std::string, std::pair<int64_t, int64_t>>;

int main() {<!-- -->
    Elem e1 = 42;
    Elem e2 = "Hello, world!";
    Elem e3 = 3.14;
    Elem e4 = std::make_pair(10, 20);

    if (std::holds_alternative<int32_t>(e1)) {<!-- -->
        int32_t value = std::get<int32_t>(e1);
        cout << "e1 is an int32_t: " << value << endl;
    }

    if (std::holds_alternative<std::string>(e2)) {<!-- -->
        std::string value = std::get<std::string>(e2);
        cout << "e2 is a string: " << value << endl;
    }

    if (std::holds_alternative<double>(e3)) {<!-- -->
        double value = std::get<double>(e3);
        cout << "e3 is a double: " << value << endl;
    }

    if (std::holds_alternative<std::pair<int64_t, int64_t>>(e4)) {<!-- -->
        std::pair<int64_t, int64_t> value = std::get<std::pair<int64_t, int64_t>>(e4);
        cout << "e4 is a pair: (" << value.first << ", " << value.second << ")" << endl;
    }

    return 0;
}

<6>.v6.0 comprehensive application examples

#include <iostream>
#include <string>
#include<typeinfo>
#include <variant>
#include <map>

using namespace std;

class Item {<!-- -->
public:

  template<typename S, typename T>
  Item & amp;set(S key, T value) {<!-- -->
    printf("xxx---------->%s(), line = %d, key = %s, vlaue = %d\
",__FUNCTION__,__LINE__,key,value);
    //The findOrAllocateProp function returns the Prop object and then calls the set() function. Finally, the key value is set to mName and the value is set to mElem.
    findOrAllocateProp(key).set(value);
    return *this;
  }

  Item & amp;setInt32(const char *key, int32_t value) {<!-- -->
    printf("xxx---------->%s(), line = %d, key = %s, vlaue = %d\
",__FUNCTION__,__LINE__,key,value);
    return set(key, value);
  }

  class Prop {<!-- -->
  public:
    using Elem = std::variant<std::monostate, int32_t, int64_t, double, std::string, std::pair<int64_t, int64_t>>;

    //1.Set the key value to mName
    void setName(const char *name) {<!-- -->
      printf("xxx---------->%s(), line = %d, name = %s\
",__FUNCTION__,__LINE__,name);
      mName = name;
    }

    //2. Pass valuec to mElem.
    template <typename T> void set(const T & amp; value) {<!-- -->
      printf("xxx---------->%s(), line = %d, value = %d\
",__FUNCTION__,__LINE__,value);
      mElem = value;

      //Get the value in mElem.
      int32_t val = std::get<int32_t>(mElem);
      printf("xxx---------->%s(), line = %d,val = %d\
",__FUNCTION__,__LINE__,val);
    }

  public:
    std::string mName;
    Elem mElem;
  };

  //findOrAllocateProp function returns the Prop object and then calls the set() function
  Prop & amp;findOrAllocateProp(const char *key) {<!-- -->
    auto it = mProps.find(key);//The value corresponding to the starting key is empty.

    if (it != mProps.end()){<!-- -->//Do not take this branch.
      return it->second;
    }

    Prop &prop = mProps[key];
    prop.setName(key);
    printf("xxx---------->%s(), line = %d, key = %s, nName = %s\
",__FUNCTION__,__LINE__,key,prop.mName.c_str( ));
    return prop;
  }

  std::map<std::string, Prop> mProps;
};

int main(){<!-- -->
  Item it;
  it.setInt32("Tom", 18);


}


<7>.v7.0

#include <iostream>
#include <string>
#include<typeinfo>
#include <variant>
#include <map>

using namespace std;

class Item {<!-- -->
public:

  template<typename S, typename T>
  Item & amp;set(S key, T value) {<!-- -->
    printf("xxx---------->%s(), line = %d, key = %s, vlaue = %d\
",__FUNCTION__,__LINE__,key,value);
    //The findOrAllocateProp function returns the Prop object and then calls the set() function. Finally, the key value is set to mName and the value is set to mElem.
    findOrAllocateProp(key).set(value);

    //Or
    // Prop m_prop = findOrAllocateProp(key);
    // printf("xxx---------->%s(), line = %d, key = %s, value = %d\
",__FUNCTION__,__LINE__,m_prop.mName.c_str( ),std::get<int32_t>(m_prop.mElem));
    return *this;
  }

  Item & amp;setInt32(const char *key, int32_t value) {<!-- -->
    printf("xxx---------->%s(), line = %d, key = %s, vlaue = %d\
",__FUNCTION__,__LINE__,key,value);
    return set(key, value);
  }

  //key: mName; value:mElem.
  class Prop {<!-- -->
  public:
    using Elem = std::variant<std::monostate, int32_t, int64_t, double, std::string, std::pair<int64_t, int64_t>>;

    //1.Set the key value to mName
    void setName(const char *name) {<!-- -->
      printf("xxx---------->%s(), line = %d, name = %s\
",__FUNCTION__,__LINE__,name);
      mName = name;
    }

    //2. Pass valuec to mElem.
    template <typename T> void set(const T & amp; value) {<!-- -->
      mElem = value;
      //Get the value in mElem.
      int32_t val = std::get<int32_t>(mElem);
      printf("xxx---------->%s(), line = %d,val = %d\
",__FUNCTION__,__LINE__,val);
    }

  public:
    std::string mName;//key
    Elem mElem;//value
  };

  //findOrAllocateProp function returns the Prop object and then calls the set() function
  Prop & amp;findOrAllocateProp(const char *key) {<!-- -->
    auto it = mProps.find(key);//The value corresponding to the starting key is empty.

    if (it != mProps.end()){<!-- -->//Do not take this branch.
      return it->second;
    }

    Prop &prop = mProps[key];
    prop.setName(key);
    return prop;
  }

  std::map<std::string, Prop> mProps;
};

int main(){<!-- -->
  Item it;
  it.setInt32("Tom", 18);
}