Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::variant for boost::arrays of arbitrary size

Tags:

c++

arrays

boost

I'd like to create a boost::variant in the spirit of

typedef boost::variant<boost::array<int, 1>, boost::array<int, 2>, boost::array<int, 3>, ... > any_int_array;

generalized to N for the second value of the template. In other words, a boost::variant that holds arrays of any size. Is this possible?

Note that in the example above, boost::array is one of my cases, but it needs to be a viable solution for any class that takes a single int value as a template parameter.

like image 873
mikesol Avatar asked May 12 '14 11:05

mikesol


People also ask

What is the difference between Boost array and array in C++?

Update: std::array is (as of C++11) part of the C++ standard. The differences between boost::array and std::array are minimal. If you are using C++11, you should consider using std::array instead of boost::array .

What is a variant in boost?

boost::variant is defined in boost/variant.hpp. Because boost::variant is a template, at least one parameter must be specified. One or more template parameters specify the supported types. In Example 24.1, v can store values of type double, char, or std::string.

When operator [] is called on an array of type boost?

When operator [] is called on an array of type boost::multi_array, the return value depends on the number of dimensions. In Example 19.1, the operator returns char elements because the array accessed is one dimensional. In Example 19.2, a is a two-dimensional array.

What is multi_array in boost?

It is defined in boost/multi_array.hpp. boost::multi_array is a template expecting two parameters: The first parameter is the type of the elements to store in the array. The second parameter determines how many dimensions the array should have.


Video Answer


1 Answers

Since you're talking about types with a statically known capacity, can't you dig your way out of this hole with some template metapgrogramming?

Live on Coliru:

#include <boost/variant.hpp>
#include <boost/array.hpp>
#include <bitset>
#include <iostream>

template <template <typename, size_t> class T, typename V, size_t N>
    void foo(T<V, N> const& something)
    {
        std::cout << __LINE__ << ": " << __PRETTY_FUNCTION__ << "\n";
    }

template <template <size_t> class T, size_t N>
    void foo(T<N> const& something)
    {
        std::cout << __LINE__ << ": " << __PRETTY_FUNCTION__ << "\n";
    }

int main()
{
    boost::array<int, 67> a;
    boost::array<double, 78> b;
    std::bitset<47> c;

    foo(a);
    foo(b);
    foo(c);
}

Printing

9: void foo(const T<V, N> &) [T = array, V = int, N = 67]
9: void foo(const T<V, N> &) [T = array, V = double, N = 78]
15: void foo(const T<N> &) [T = bitset, N = 47]

Update

Brainwave: I just realized that std::array<> is specified to be a POD (trivial) type. As such, the layout MUST be standard, and the size MUST be identical to the equivalent T[N] array. Due to these restrictions, you can safely cast any std::array<T, M> to std::array<T, N>& (with matching const/volatile qualification) as long as N>0 and N<=M.

Conversely, the storage required for

variant<array<T, 1>, array<T, 1>, array<T, 1>, .... array<T, 1000> >

will always be at least sizeof array<T, 1000> + overhead for the type discriminator (which()). There is no gain in making the distinction between all the other distinct array<> instantiations if only the dimensions vary

like image 156
sehe Avatar answered Oct 10 '22 21:10

sehe