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.
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 .
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::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.
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.
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]
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With