With C++11 i have the something like
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/size.hpp>
#include <boost/array.hpp>
#include <iostream>
namespace mpl = boost::mpl;
template<std::size_t ... Args>
struct Test
{
typedef mpl::vector_c<std::size_t, Args ...> values_type;
static const boost::array<std::size_t, sizeof...(Args)> values;
};
int main (int argc, char** argv)
{
Test<3,2,5,6,7> test;
return 0;
}
I would like to initialize the boost::array contents with the values 'contained' in the mpl::vector_c. This initialization should be performed at compile time. I have seen on SO some solutions using the preprocessor, but I have no idea on how to apply them to the variadic template case.
Notice that in the above sample code, the elements of the mpl::vector_c are the same as Test's template parameters. In the actual code it is not the case, instead values_type
has length == number of template arguments, but the actual values result from the application of a sequence of mpl algorithms. Therefore, do not assume that the argument are the same.
Hope the question is clear, thanks!
One method is to use at_c
to extract the vector_c into a parameter pack, and then expand it and use it to initialize the array.
#include <cstdio>
#include <array>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
#include <utils/vtmp.hpp>
// ^ https://github.com/kennytm/utils/blob/master/vtmp.hpp
template <typename MPLVectorType>
class to_std_array
{
typedef typename MPLVectorType::value_type element_type;
static constexpr size_t length = boost::mpl::size<MPLVectorType>::value;
typedef std::array<element_type, length> array_type;
template <size_t... indices>
static constexpr array_type
make(const utils::vtmp::integers<indices...>&) noexcept
{
return array_type{{
boost::mpl::at_c<MPLVectorType, indices>::type::value...
}};
}
public:
static constexpr array_type make() noexcept
{
return make(utils::vtmp::iota<length>{});
}
};
int main()
{
typedef boost::mpl::vector_c<size_t, 3, 2, 5, 6, 7> values;
for (size_t s : to_std_array<values>::make())
printf("%zu\n", s);
return 0;
}
I am using std::array
here, but you could simply change it to boost::array
and it still works. The expression
to_std_array<MPLVector>::make()
is run in compile-time because the make()
function is constexpr
.
The same technique is usually used in expanding a std::tuple
into a std::array
( Convert std::tuple to std::array C++11), into a function call ( "unpacking" a tuple to call a matching function pointer), etc.
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