未知std::array尺寸时如何将boost::any转换为std::array<int, size>
boost::any with Unknown-Size std::array The core issue here is that std::array<int, N> is a distinct type for every different N—the size is part of the type's template parameters. Since boost::any stores a concrete type, you can't directly cast it to a generic std::array<int, ?> without knowing N upfront. Here are two practical solutions depending on your use case:
1. Try Casting Against Known/Expected Sizes
If you have a limited, predictable range of possible array sizes, you can iterate through those sizes and attempt boost::any_cast for each one. This is straightforward but only works if you can enumerate all possible sizes.
#include <boost/any.hpp> #include <array> #include <iostream> #include <stdexcept> // Helper template to attempt casting to a specific array size template <std::size_t N> bool try_extract_array(const boost::any& any_val, std::array<int, N>& result) { try { result = boost::any_cast<std::array<int, N>>(any_val); return true; } catch (const boost::bad_any_cast&) { return false; } } int main() { boost::any x; std::array<int, 3> arr = {1, 2, 3}; x = arr; // Try common sizes you expect std::array<int, 1> arr1; if (try_extract_array(x, arr1)) { // Handle size 1 array } std::array<int, 3> arr3; if (try_extract_array(x, arr3)) { std::cout << "Extracted size-3 array: " << arr3[0] << ", " << arr3[1] << ", " << arr3[2] << "\n"; } // Add more checks for other expected sizes as needed }
2. Use Type Erasure for Flexible Array Handling
For cases where array sizes are arbitrary or unbounded, wrap your std::array in a type-erased interface. This lets you store any size of std::array<int, N> in boost::any and access elements/size without knowing N at compile time.
#include <boost/any.hpp> #include <array> #include <iostream> #include <memory> #include <stdexcept> // Base class for type-erased integer arrays class ErasedIntArray { public: virtual ~ErasedIntArray() = default; virtual std::size_t size() const = 0; virtual int at(std::size_t index) const = 0; // Add a non-const version if you need to modify elements virtual int& at(std::size_t index) = 0; }; // Template wrapper for concrete std::array<int, N> template <std::size_t N> class IntArrayWrapper : public ErasedIntArray { private: std::array<int, N> m_array; public: explicit IntArrayWrapper(std::array<int, N> arr) : m_array(std::move(arr)) {} std::size_t size() const override { return N; } int at(std::size_t index) const override { if (index >= N) throw std::out_of_range("Array index out of bounds"); return m_array[index]; } int& at(std::size_t index) override { if (index >= N) throw std::out_of_range("Array index out of bounds"); return m_array[index]; } }; int main() { boost::any x; std::array<int, 5> arr = {10, 20, 30, 40, 50}; // Store a shared_ptr to the wrapped array in boost::any x = std::make_shared<IntArrayWrapper<5>>(arr); // Extract and use the type-erased array if (auto wrapped_ptr = boost::any_cast<std::shared_ptr<ErasedIntArray>>(&x)) { auto& array = **wrapped_ptr; std::cout << "Array size: " << array.size() << "\n"; for (std::size_t i = 0; i < array.size(); ++i) { std::cout << "Element " << i << ": " << array.at(i) << "\n"; } } }
Pros and Cons
- Try-Cast Approach: Simple to implement, no extra boilerplate. But it's inflexible—only works if you can predict all possible array sizes.
- Type Erasure Approach: Fully flexible for any array size, but requires writing wrapper classes and uses dynamic polymorphism (minor runtime overhead).
内容的提问来源于stack exchange,提问作者Annu_the_coder

