以通用方式对 std::variant<POD_PTR*...> 执行操作

问题描述

说出下面的variant
using Variant = std::variant<uint32_t*,uint16_t*>

然后,需要 vector 个这样的 variant
using VariantVecType = std::vector<Variant>

如何访问底层值(由这些指针指向)以更通用的方式(即不使用 std::get_if)对它们执行算术运算,例如

   uint32_t i0 = 1;
   uint16_t i1 = 2;

   Variant v0{ &i0 };
   Variant v1{ &i1 };

   VariantVecType vec{v0,v1};

   for(auto& v : vec)
        if(auto pval = std::get_if<uint32_t*>(&v))
            std::cout << "Underlying int value: " << *(*pval) << '\n';  
        else if(auto pval = std::get_if<uint16_t*>(&v))
            std::cout << "Underlying int value: " << *(*pval) << '\n';  
        else
            std::cout << "Failed to get value!" << '\n';

解决方法

通常您会使用 std::visit

示例

#include <iostream>
#include <variant>
#include <cstdint>
#include <vector>

// from cppref:
// helper type for the visitor #4
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
// explicit deduction guide (not needed as of C++20)
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
 

int main() {
    uint32_t i0 = 1;
    uint16_t i1 = 2;

    using Variant = std::variant<uint32_t*,uint16_t*>;
    Variant v0{ &i0 };
    Variant v1{ &i1 };

    using VariantVecType = std::vector<Variant>;
    VariantVecType vec{v0,v1};

   for(auto& v : vec) {
       std::visit(overloaded {
            [](uint32_t* arg) { std::cout << "Underlying uint32 value: " << *arg << '\n'; },[](uint16_t* arg) { std::cout << "Underlying uint16 value: " << *arg << '\n'; },},v);
   }
}

但是 std::variant<uint32_t*,uint16_t*> 似乎有点尴尬。 64 位机器中的指针比这两种类型都大。并且访问元素需要indirection=slow。另外,这两种类型的算术将大致相同(溢出除外)。那么为什么没有一个正常的 std::vector<uint32_t>