在 C 中,如何在運行時列印變體中包含的型別?
我的用例:使用pybind11將值字典從 Python 傳遞到 C ,我想列印出接收到的型別。
uj5u.com熱心網友回復:
std::visit您可以使用一些型別名稱列印庫(例如 Boost.TypeIndex)獲得通用解決方案。一個典型的解決方案:
#include <iostream>
#include <type_traits>
#include <variant>
#include <boost/type_index.hpp>
int main()
{
std::variant<char, bool, int, double> v;
auto print_variant_type =
[](auto&& value)
{
using T = std::decay_t<decltype(value)>;
std::cout << boost::typeindex::type_id<T>().pretty_name() << std::endl;
};
v = 'a';
std::visit(print_variant_type, v); // prints out "char"
v = true;
std::visit(print_variant_type, v); // prints out "bool"
v = 1;
std::visit(print_variant_type, v); // prints out "int"
v = 1.0;
std::visit(print_variant_type, v); // prints out "double"
}
現場演示:https ://godbolt.org/z/Web5zeGof
唯一的缺點是它可以為型別別名的庫型別(例如std::string)列印“丑陋”的型別名稱。可能更適合您的特定變體實體的替代方法可能是使用從變體索引到型別名稱的映射:
using variant_type = std::variant<char, bool, int, double, std::string>;
static const std::array variant_type_names =
{ "char", "bool", "int", "double", "std::string" };
void print_variant_type(const variant_type& v)
{
assert(v.index() < variant_type_names.size());
std::cout << variant_type_names[v.index()] << std::endl;
}
int main()
{
variant_type v;
v = 'a';
print_variant_type(v); // prints out "char"
v = true;
print_variant_type(v); // prints out "bool"
v = 1;
print_variant_type(v); // prints out "int"
v = 1.0;
print_variant_type(v); // prints out "double"
v = std::string("some string");
print_variant_type(v); // prints out "std::string"
}
現場演示:https ://godbolt.org/z/9na1qzEKs
uj5u.com熱心網友回復:
您可以像這樣使用函式多載:
#include <iostream>
#include <variant>
using VariantT = std::variant<int, float>;
namespace {
std::string name(const float& ) {
return "float";
}
std::string name(const int& ) {
return "int";
}
std::string variantName(const VariantT& v) {
return std::visit(
[](const auto &v) { return name(v); },
v
);
}
}
int main() {
std::variant<int, float> v;
v = 1;
std::cout << variantName(v) << std::endl;
v = 1.f;
std::cout << variantName(v) << std::endl;
}
uj5u.com熱心網友回復:
在 MSVC 2022 和 C 17 下測驗。應該在 gcc 和 clang 上作業,但未經測驗。
#include <string>
#include <variant>
#include <type_traits>
/**
* \brief Variant type to string.
* \tparam T Variant type.
* \param v Variant.
* \return Variant type as a string.
*/
template<typename T>
std::string variant_type_string(T v)
{
std::string result;
if constexpr(std::is_constructible_v<T, int>) { // Avoids compile error if variant does not contain this type.
if (std::holds_alternative<int>(v)) { // Runtime check of type that variant holds.
result = "int";
}
}
else if constexpr(std::is_constructible_v<T, std::string>) {
if (std::holds_alternative<std::string>(v)) {
result = "string";
}
}
else if constexpr(std::is_constructible_v<T, bool>) {
if (std::holds_alternative<bool>(v)) {
result = "bool";
}
}
else {
result = "?";
}
return result;
}
要使用:
std::variant<int, std::string> v { 42 };
std::cout << variant_type_string(v);
// Prints: int
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/530973.html
