How do I add the numbers?
typedef boost::mpl::vector<
boost::mpl::int_<1>, boost::mpl::int_<2>,
boost::mpl::int_<3>, boost::mpl::int_<4>,
boost::mpl::int_<5>, boost::mpl::int_<6> > ints;
typedef boost::mpl::accumulate<ints, boost::mpl::int_<0>, ????? >::type sum;
EDIT: I was wrong, you can use mpl::plus directly, using the placeholder expressions. This simplifies the whole notation:
typedef mpl::accumulate<ints, mpl::int_<0>, mpl::plus<mpl::_1, mpl::_2> >::type sum;
Of course it is also possible to obtain the same effect using a metafunction class (which for adding is an overkill, but for something more complex might be reasonable):
struct plus_mpl
{
template <class T1, class T2>
struct apply
{
typedef typename mpl::plus<T1,T2>::type type;
};
};
typedef mpl::accumulate<ints, mpl::int_<0>, plus_mpl >::type sum;
Related
I was reading this tutorial on variadic templates, but in below code:
template<int index, class C>
struct container_index {
// points to the "next" container type
typedef typename container_index<
index-1,
typename C::base_container
>::container_type container_type;
// points to the next T-type
typedef typename container_index<
index-1,
typename C::base_container
>::type type;
};
these typedefs seems redundant but it compiles well. The problem is simply I dont understand why they are like this and I didnt find a tutorial explaining this case. Could someone give some explanation? Why the typedef name is repeated:
"::container_type container_type;"
"::type type;"
It couldn't be just like that:
typedef typename container_index<
index-1,
typename C::base_container
> type;
Many thanks.
The example demonstrates a recursive type definition in templates. The key is that the recursion base case is specified as a specialisation for index=0:
template<class C>
struct container_index<0, C> {
// point to C instead of C::base_container
typedef C container_type;
// point to C::type instead of C::base_container::type
typedef typename C::type type;
};
It is this base-case that makes the type deduction possible. So for example, the type container_index<2, MyCont>::container_type is expanded to container_index<1, MyCont>::container_type, which in turn expands to container_index<0, MyCont>::container_type, which finally expands to MyCont.
typedef gives a type a name. So you need to supply both the type and the name you want to give it.
In
typedef typename container_index<index-1, typename C::base_container>::type type;
the typename container_index<index-1, typename C::base_container>::type is us describing the type we want to give a name to, and that final type before the semicolon is the name we want to call it.
Compare:
struct Example
{
typedef Fruit::orange citrus; // declare a type called Example::citrus, which is the same type as Fruit::orange
typedef Fruit::apple apple; // declare a type called Example::apple, which is the same type as Fruit::apple - the same operation as the line above, and so the same syntax!
};
Given:
boost::variant<T1,T2,T3,...,TN>
Calculate the following at compile time:
max(sizeof(T1), sizeof(T2), sizeof(T3),... ,sizeof(TN))
I had no idea how to approach this, but this answer shed some light on how I might get started. Using the code in that answer with two types, T1 and T2, I could use the following in a source file to get the size of the larger object:
size_t largestSize = sizeof(largest<T1, T2>::type);
This is exactly what I'd like to do, but I need the largest template to work with more than two classes - specifically, it would need to check all types stored in a boost::variant object.
I know that boost::variant has a types typedef, which defines some sort of list of types in the variant. The problem is, I get totally lost when I try to wrap my head around all the boost::mpl stuff in the implementation. I don't intuitively understand what boost::variant::types is, and how I might be able to pass it into my own template that does something with it.
In my head, this is what the final implementation might look like:
typedef boost::variant<T1, T2, T3, T4> MyVariant;
size_t largestSize = sizeof(largest<MyVariant::types>::type);
Unfortunately, I have no idea how to go about implementing this version of largest.
I'm not sure if this is a reasonable approach, so I'm open to any other ways to accomplish this (maybe apply a boost::static_visitor to all types at compile time?).
Just ignore the mpl stuff. Start with:
template <class T> struct max_variant_sizeof;
template <class... Ts>
struct max_variant_sizeof<boost::variant<Ts...>> {
static constexpr size_t value = variadic_max(sizeof(Ts)...);
};
Now max_variant_sizeof<MyVariant>::value will forward all the sizes of all the types to a function. All you need to do is write that variadic_max:
constexpr size_t variadic_max(size_t v) { return v; }
template <class... Args>
constexpr size_t variadic_max(size_t a, size_t b, Args... cs)
{
return variadic_max(std::max(a, b), cs...);
}
Before C++14, std::max() isn't constexpr, so that can be replaced with:
return variadic_max((a > b ? a : b), cs...);
One thing worth noting about:
maybe apply a boost::static_visitor to all types at compile time?
Visitation with a variant is a runtime operation - your visitor gets called with the type that the variant happens to be holding on to. It will not be called with all the types.
You could also change the code from the link you attached to:
template <class First, class... Args>
struct largest: largest<First, typename largest<Args...>::type> {
};
template<bool, typename T1, typename T2>
struct is_cond {
typedef T1 type;
};
template<typename T1, typename T2>
struct is_cond<false, T1, T2> {
typedef T2 type;
};
template<typename T1, typename T2>
struct largest<T1, T2> {
typedef typename is_cond< (sizeof(T1)>sizeof(T2)), T1, T2>::type type;
};
Then the usage could look like:
cout << sizeof(largest<int, char, double>::type) << endl;
Edit:
To make it work with boost::variant as well as any other variadic args templated class just add another specialization:
template <template <class...> class Var, class... Args>
struct largest<Var<Args...>>: largest<Args...> { };
Then usage could look e.g. (with tuple, that can be successfully changed to boost::variant):
cout << sizeof(largest<tuple<int, char, double>>::type) << endl;
I have using the boost::mpl library as a generic library for compile time code operations.
Some header code preparation:
#include <boost/mpl/vector.hpp>
#include <boost/mpl/max_element.hpp>
#include <boost/mpl/transform_view.hpp>
#include <boost/mpl/sizeof.hpp>
#include <boost/type_traits/alignment_of.hpp>
// alignof_ headers
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/aux_/na_spec.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
// alignof mpl style implementation (namespace injection) the same way as the `mpl::sizeof_` did
namespace boost {
namespace mpl {
template<
typename BOOST_MPL_AUX_NA_PARAM(T)
>
struct alignof_
: mpl::size_t< boost::alignment_of<T>::value >
{
BOOST_MPL_AUX_LAMBDA_SUPPORT(1, alignof_, (T))
};
BOOST_MPL_AUX_NA_SPEC_NO_ETI(1, alignof_)
}
}
'
Some helper macro:
// generates compilation error and shows real type name (and place of declaration in some cases) in an error message, useful for debugging boost::mpl recurrent types
// old C++ standard compatible
//#define UTILITY_TYPE_LOOKUP_BY_ERROR(type_name) \
// (*(::utility::type_lookup<type_name >::type*)0).operator ,(*(::utility::dummy*)0)
// can be applied in a class, but requires `decltype` support
#define UTILITY_TYPE_LOOKUP_BY_ERROR(type_name) \
typedef decltype((*(::utility::type_lookup<type_name >::type*)0).operator ,(*(::utility::dummy*)0)) _type_lookup_t
namespace utility
{
struct dummy {};
template <typename T>
struct type_lookup
{
typedef T type;
};
}
'
Usage example:
namespace mpl = bost::mpl;
typedef mpl::vector<T1, T2, T3, T4, T5> storage_types_t;
typedef typename mpl::deref<
typename mpl::max_element<
mpl::transform_view<storage_types_t, mpl::sizeof_<mpl::_1> >
>::type
>::type max_size_t; // type has stored max sizeof(T1, T2, T3, T4, T5)
typedef typename mpl::deref<
typename mpl::max_element<
mpl::transform_view<storage_types_t, mpl::alignof_<mpl::_1> >
>::type
>::type max_alignment_t; // type has stored max alignof(T1, T2, T3, T4, T5)
// testing on real values
UTILITY_TYPE_LOOKUP_BY_ERROR(max_size_t);
UTILITY_TYPE_LOOKUP_BY_ERROR(max_alignment_t);
'
Visual Studio 2015 error output:
error C2039: ',': is not a member of 'boost::mpl::size_t<**calculated max sizeof here**>'
error C2039: ',': is not a member of 'boost::mpl::size_t<**calculated max alignment here**>'
Consider this:
template < typename VectorType >
void ff()
{
// This passes.
typedef typename VectorType::value_type VV;
typedef int VV::* MM;
// This FAILS!??
typedef int typename VectorType::value_type::* MMM;
}
Why the second fails and what is the correct way to get the desired typedef in one typedef statement?
My compiler is the GCC-4.7.2.
As pointed out in the comments, you have a typename where it shouldn't be:
typedef int typename VectorType::value_type::* MMM;
should be just:
typedef int VectorType::value_type::* MMM;
typename is used when you have a::b inside a template, a depends on template parameters and b is a type. In that case, you have to use typename a::b to communicate this fact to the compiler.
On the other hand, you're doing a::b::*, which is a clear indicator that b must be a type, so typename cannot be used here.
I was wondering if it is possible to have some kind of parameterized typedef.
To illustrate, in my code I use this typedef:
typedef std::queue<std::vector<unsigned char>, std::deque<std::vector<unsigned char> > > UnsignedCharQueue;
As you can see this is a rather unwieldy construct so the typedef makes sense. However, if I want to have queues with other datatypes I need to define them beforehand explizitly.
So I was thinking if it were possible to use a construct like this:
typedef std::queue<std::vector<T>, std::deque<std::vector<T> > > Queue<T>;
private:
Queue<unsigned char> mMyQueue;
Similar like generics in Java.
In C++11, you can use template aliases, such as in:
template<typename T>
using my_alias = some_class_template<T>;
// ...
my_alias<T> obj; // Same as "some_class_template<T> obj;"
So in your case it would be:
template<typename T>
using Queue = std::queue<std::vector<T>, std::deque<std::vector<T> > >;
Also notice, that in C++11 you do not need to leave a space between closed angle brackets, so the above can be rewritten as follows:
template<typename T>
using Queue = std::queue<std::vector<T>, std::deque<std::vector<T>>>;
// ^^^
In C++03 you could define a Queue metafunction this way:
template<typename T>
struct Queue
{
typedef std::queue<std::vector<T>, std::deque<std::vector<T> > > type;
};
Which you would then use this way:
Queue<int>::type obj;
If you are using it in a template with parameter T (as in the following), do not forget the typename disambiguator:
template<typename T>
struct X
{
typename Queue<T>::type obj;
// ^^^^^^^^
}
Yes, it works like this:
template <typename T> using Queue = std::queue<std::vector<T>, std::deque<std::vector<T> > >;
I have a list of types, from which I want to construct the list of all combinations with two elements. For example:
namespace mpl = boost::mpl;
typedef mpl::vector<int, long> typelist;
// mpl magic...
// the wanted list is equivalent to:
typedef mpl::vector<pair<int, int>, pair<int, long>,
pair<long, int>, pair<long, long> > combinations;
Here, pair<T1,T2> could be std::pair<T1,T2>, or mpl::vector<T1,T2>.
How to do this?
I would also be interested in removing the duplicates when we consider that pair<T1, T2> == pair<T2, T1>.
Thanks.
The list of combinations of a single type int with the list of types mpl::vector<int, long> can be computed by invoking mpl::fold:
typedef fold<
mpl::vector<int, long>, vector<>,
push_back<mpl::_1, std::pair<int, mpl::_2> >
>::type list_of_pairs;
Now, if we wrap that into a separate meta-function and invoke it for all types of the initial typelist we get:
typedef mpl::vector<int, long> typelist;
template <typename T, typename Result>
struct list_of_pairs
: mpl::fold<typelist, Result,
mpl::push_back<mpl::_1, std::pair<T, mpl::_2> > >
{};
typedef mpl::fold<
typelist, mpl::vector<>, mpl::lambda<list_of_pairs<mpl::_2, mpl::_1> >
>::type result_type;
BOOST_MPL_ASSERT(
mpl::equal<result_type,
mpl::vector4<
std::pair<int, int>, std::pair<int,long>,
std::pair<long,int>, std::pair<long,long>
> >::value);
EDIT: answering second question:
Making the result containing only unique elements (in the sense you mentioned) is a bit more involved. First you need to define a meta function comparing two elements and returning mpl::true_/mpl::false_:
template <typename P1, typename P2>
struct pairs_are_equal
: mpl::or_<
mpl::and_<
is_same<typename P1::first_type, typename P2::first_type>,
is_same<typename P1::second_type, typename P2::second_type> >,
mpl::and_<
is_same<typename P1::first_type, typename P2::second_type>,
is_same<typename P1::second_type, typename P2::first_type> > >
{};
Then we need to define a meta-function which tries to find a given element in a given list:
template <typename List, typename T>
struct list_doesnt_have_element
: is_same<
typename mpl::find_if<List, pairs_are_equal<mpl::_1, T> >::type,
typename mpl::end<List>::type>
{};
Now, this can be utilized to build a new list, making sure no duplicates are inserted:
typedef mpl::fold<
result_type, mpl::vector<>,
mpl::if_<
mpl::lambda<list_doesnt_have_element<mpl::_1, mpl::_2> >,
mpl::push_back<mpl::_1, mpl::_2>, mpl::_1>
>::type unique_result_type;
All this is from the top of my head, so it may need some tweaking here or there. But the idea should be correct.
EDIT: minor corrections as outlined by #rafak
Excellent question. There are many interesting ways to solve this. Here is one.
All the unqualified names are in the mpl namespace, except for _1 and _2 which are in mpl::placeholders and boost::is_same, which is found in the type_traits library. The first template is a helper class to generate a list of all pairs consisting of a single element and each element of the given sequence. The second template aggregates all the results together to form the final sequence. Note that the results are not in a vector. You can do that easily with mpl::copy.
template <class Elem, class Seq>
struct single_combo {
typedef typename transform<Seq
,lambda< std::pair<Elem, _1> >
>::type type;
};
template <class Seq>
struct combo {
typedef typename unique<Seq, is_same<_1,_2> >::type U;
typedef typename fold<
typename transform<U
,lambda< single_combo<_1, U> >
>::type
,empty_sequence
,lambda< joint_view<_1,_2> >
>::type type;
};
typedef typename combo<typelist>::type combinations;
Side note: If you're reading this and want a challenge, try answering this question yourself. It's a great plunge into MPL.
I've been doing some metaprogramming myself lately, have you looked into boost::mpl::set? That will eliminate duplicates. As for combinations, that sounds to me like mapping, what about boost::mpl::map? Beware that there are library limits that are imposed on the limits of types the sequences can take, though this can be adjusted with a macro, you're still at the mercy of your compiler's upper limit, depending on the number of types you need to handle.