Passing iterators to class functions - c++

I'm trying to create a new templated class "CrazyBucket< T >" which has to hold multiple values of type T.
I want to create a constructor for this class that can accept any 2 forward iterators as its arguments and copy in those values (of type T) to the class instance.
Constructor:
CrazyBucket< T >::CrazyBucket( iterator< forward_iterator_tag, T > start, iterator< forward_iterator_tag, T > end )
{ ... }
But when I try to call it with,
vector< int > vec;
vec.push_back( 4 );
CrazyBucket< int > bucket( vec.begin(), vec.end() );
I get the following error,
candidate constructor not viable: no known conversion from 'iterator' (aka '__wrap_iter<pointer>') to 'std::iterator<std::forward_iterator_tag, int>' for 1st argument
Any help with how I should define my constructor is much appreciated.
Thanks in advance.

You can use SFINAE to exclude non-matching types in a fashion I think is close to what you want.
#include <iostream>
#include <iterator>
#include <vector>
template<class T>
class CrazyBucket
{
public:
template<class It, typename = typename std::enable_if<
std::is_same< typename std::iterator_traits<It>::value_type,T>::value>::type>
CrazyBucket(It beg, It end)
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
};
int main()
{
std::vector<int> vInt;
CrazyBucket<int> cbOK(vInt.begin(), vInt.end());
int ar[10];
CrazyBucket<int> cbAlsoOK(ar, ar+10);
// uncomment for failure test case.
//std::vector<double> vDbl;
//CrazyBucket<int> cbFail(vDbl.begin(), vDbl.end());
}
Also accomplished with a static assertion:
template<class It>
CrazyBucket(It beg, It end)
{
static_assert(std::is_same<T, typename std::iterator_traits<It>::value_type>::value,
"failed to match iterator value type");
std::cout << __PRETTY_FUNCTION__ << '\n';
}
Either is restrictive, and you should know that may not be the end goal you had in mind. For example, an iteration of short will naturally store as int without data loss, yet this kind of SFINAE will toss it. That too can be overcome with more expansion, but by that time I think you need to consider whether it is really worth it in the end.
Anyway, best of luck.

Does it really have to be the constructor? The problem as I see it is that you'd need to have a specialized constructor which isn't possible as per the standard. If you can defer your initialisation to a member function then the following approach will work:
template<class T>
struct CrazyContainer {
template<class U>
void init(U first,U last) {
for(auto it=first;it!=last;it++) {
// do stuff with 'it'
}
}
};
main() {
std::vector<int> vec;
CrazyContainer<int> f;
f.init(vec.begin(),vec.end());
}
I'm looking forward to seeing if there's someone else that can come up with a way that permits this via a constructor.
Edit:
Thanks to Sebastian for pointing out that a templated constructor will work just as well as the templated method:
template<class T>
struct CrazyContainer {
template<class U>
CrazyContainer(U first,U last) {
for(auto it=first;it!=last;it++) {
// do stuff
}
}
};
main() {
std::vector<int> v;
std::set<int> s;
CrazyContainer<int> cv(v.begin(),v.end());
CrazyContainer<int> cs(s.begin(),s.end());
}

Related

How to allow only iterators with a ceratin value_type?

I want to write a class that takes a pair of iterators as parameters to the constructor, but I dont know how to raise an error at compile-time when those iterators' value_type doesn't match an expected type. This is what I tried using typeid:
#include <vector>
struct foo {
std::vector<double> data;
template <typename IT>
foo(IT begin, IT end){
typedef int static_assert_valuetype_is_double[
typeid(typename IT::value_type) == typeid(double) ? 1 : -1
];
std::cout << "constructor called \n";
data = std::vector<double>(begin,end);
}
};
int main()
{
std::vector<double> x(5);
foo f(x.begin(),x.end()); // double: ok
std::vector<int> y(10);
foo g(y.begin(),y.end()); // int: should not compile
}
Note that in this case, int to double would be fine, but thats just an example and in the real code the types have to match exactly. To my surprise in both cases, the constructor works without errors (there is only a warning about the unused typedef). Does the -1 sized array static assert trick not work when the typedef is declared inside a method? How do I produce an error when IT::value_type is the wrong type?
PS: would be nice if there was an easy C++98 solution, but if this gets too complicated, I could also accept a C++11 solution.
In modern C++, you could have used std::is_same and static_assert:
static_assert(std::is_same_v<typename std::iterator_traits<IT>::value_type, double>,
"wrong iterator");
See also std::iterator_traits: an iterator it is not guaranteed to have a value_type typedef, and one should use std::iterator_traits<it>::value_type instead.
In C++ 98, is_same is trivial to implement, static_assert needs a negative-size array trick or the BOOST_STATIC_ASSERT.
For a solution that works in C++98 and later.....
#include <iterator>
template<class T> struct TypeChecker
{};
template<> struct TypeChecker<double>
{
typedef double valid_type;
};
template <typename IT>
void foo(IT begin, IT end)
{
typename TypeChecker<typename std::iterator_traits<IT>::value_type>::valid_type type_checker;
(void)type_checker;
// whatever
}
Instantiations of foo() will succeed for any for an iterator for which value_type is double, and fail to compile otherwise.
The premise is that TypeChecker<x> does not have a valid_type for any x other than double, but we attempt to instantiate an instance of that type in foo(). The (void)type_checker prevents warnings, from some compilers about a variable that is never used, for valid types.
Here is a C++98 compliant way to implement it.....
First the fun part: Implementing a is_same is rather straightforward
template <typename T,typename U> struct is_same_type { static const bool value; };
template <typename T,typename U> const bool is_same_type<T,U>::value = false;
template <typename T> struct is_same_type<T,T> { static const bool value; };
template <typename T> const bool is_same_type<T,T>::value = true;
Now the not-so-fun part (C++11 really helps to statically assert without causing coworkers raising some eyebrows):
struct foo {
std::vector<double> data;
template <typename IT>
foo(IT begin, IT end) : data(begin,end) {
typedef int static_assert_valuetype_is_double[
is_same_type<double,typename IT::value_type>::value ? 1 : -1
];
std::cout << "constructor called \n";
}
};
int main(){
std::vector<double> x(5,2.3);
foo f(x.begin(),x.end());
for (std::vector<double>::iterator it = f.data.begin(); it != f.data.end();++it) std::cout << *it << " ";
//std::vector<int> y(10,3);
//foo g(y.begin(),y.end()); // THIS FAILS (AS EXPECTED)
}
As pointed out by others, I should actually be using std::iterator_traits<IT>::value_type as not every iterator has a value_type. However, in my case I rather want to restrict the possible iterators to a small set and disallowing iterators without a value_type isnt a problem in my specific case.
Also note that the code in the question assigned to the member, while it is of course better to use the initializer list.

Getting type from template template method parameters

I'm trying to make a method that picks a random element from a container type, like std::vector. Before, I was using this:
std::string pick_random(std::vector<std::string> c) {
int r = std::rand() % ids.size() + 1;
auto it = c.begin();
std::advance(it, r);
return *it;
}
which, as far as I could tell, worked fine. That's not to say it is fine, just that it appeared to be.
I soon had to do the same thing for another container, so I tried using template template arguments to make the method generic:
template <template<typename element_t> container_t>
element_t pick_random(container_t from) { /* ... */ }
This, however, throws an error:
element_t does not name a type
I think my intent is clear enough, but to restate it: I'm trying to get the element type of the list. I could have a separate template parameter, but then it can't properly infer the type. I've tried various different versions, but none work.
container_t is not a type, container_t<T> is.
You may use the following:
template <template<typename, typename...> C, typename T, typename...Ts>
T pick_random(const C<T, Ts...>& from);
as for std::vector, you have allocator: std::vector<T, Alloc>.
In C++14, you may simply use auto
template <typename C>
auto pick_random(const C& from) { /* ... */ }
I don't think that "template template arguments" are required here,
you could simply use the value_type from the container:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <list>
template <typename T>
typename T::value_type pick_random(T& from) {
int r = std::rand() % from.size();
auto it = from.begin();
std::advance(it, r);
return *it;
}
int main() {
std::srand(std::time(0));
std::vector<std::string> words {"the", "frogurt", "is", "also", "cursed"};
std::list<int> numbers {1, 2, 3, 4, 5};
std::cout << "words: " << pick_random(words) << std::endl;
std::cout << "numbers: " << pick_random(numbers) << std::endl;
}
value_type - the type of the values that can be obtained by dereferencing the iterator.
Source: http://en.cppreference.com/w/cpp/iterator/iterator_traits
Even better would be to avoid the arbitrary restriction on class templates. After all, why not be able to pick an element from a raw array? In order to correctly name the type in C++11, we'd have to get the result of an unqualified call to begin, which we can get via:
namespace detail {
using std::begin;
template <typename C>
auto adl_begin(C&& c) -> decltype(begin(std::forward<C>(c))) {
return begin(std::forward<C>(c));
}
}
using detail::adl_begin;
And then use that to deduce the element_type from an arbitrary container:
template <typename C>
auto pick_random(C& container) -> decltype(*adl_begin(container))
{ /* rest as before */ }
Side-note: take your container by reference, not by value.
If you're only using standard library containers then you can get the stored type out of them by using container_t::value_type.
template <typename container_t>
typename container_t::value_type pick_random(container_t& container)
{ ... }

Getting the C++ compiler to reveal what a type can be converted to

Below is a flawed (and simplified) template function that expects to work on a template arg that can be converted to one of a predefined number of types.
It happens to be 2 types, but it cold be many more.
void do_something_type_specific( const int &unused ) { std::cout << 'i'; }
void do_something_type_specific( const std::string &unused ) { std::cout << 's'; }
template< typename Iterator >
void perform_work_on_a_range( Iterator begin, Iterator end )
{
do_something_type_specific( *begin );
// Perhaps more code...
}
This happens to produce the desired results in my environment.
Template instances will compile successfully iff *Iterator produces a type that's convertible to exactly one of the choices.
However, this code unnecessarily requests that the conversion be performed and, despite unused being unused, there is still UB when begin == end.
How can this this behavior be implemented in C++03 without these problems?
Instead of dereferencing the iterator that my result in undefined behaviour when begin == end, you could try using std::iterator_traits<>. E.g.:
#include <iterator>
#include <string>
#include <cstdio>
void do_something_type_specific(std::string const&) { printf("%s\n", __PRETTY_FUNCTION__); }
void do_something_type_specific(int const&) { printf("%s\n", __PRETTY_FUNCTION__); }
template<class T>
struct ProduceValue
{
static T value;
};
template<class T>
T ProduceValue<T>::value;
// Specializations for types that can't be default constructed or must be initialized.
template<>
char* ProduceValue<char*>::value = "";
template< typename Iterator >
void perform_work_on_a_range( Iterator begin, Iterator end )
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
do_something_type_specific(ProduceValue<value_type>::value);
}
int main() {
char** p = 0;
perform_work_on_a_range(p, p);
long* q = 0;
perform_work_on_a_range(q, q);
}
Output:
void do_something_type_specific(const string&)
void do_something_type_specific(const int&)
The only inconvenience is that ProduceValue<T> has to be specialized for types that can't be default constructed or must be initialized for other reasons (like char*).
There is a boost::is_convertible metafunction that you can use to determine if a type T can be converted to some other type U.
Secondly, for begin == end, just insert a run-time check.
The problematic code in the question is trying to leverage features of both template parameters and function parameters.
Function parameters allow type conversions, but require an instantiation of the type. Template parameters don't need instantiation, but also don't perform type conversions.
The pattern below uses Boost's enable_if and is_convertible to allow template functions to be chosen by the compiler as if template parameters supported the same type conversion rules as function parameters. (Thank #dhavenith for the suggestion)
#include <boost/utility.hpp>
#include <boost/type_traits.hpp>
// enable_if_c makes the return type either void or a Substitution Failure.
template < typename T>
typename boost::enable_if_c<boost::is_convertible<T,int>::value>::type
do_something_type_specific()
{
std::cout << 'i';
}
template < typename T>
typename boost::enable_if_c<boost::is_convertible<T,std::string>::value>::type
do_something_type_specific()
{
std::cout << 's';
}
template< typename Iterator >
void perform_work_on_a_range( Iterator begin, Iterator end )
{
// This code is from #MaximYegorushkin's answer. Vote him up :)
typedef typename std::iterator_traits<Iterator>::value_type value_type;
do_something_type_specific<value_type>();
// Perhaps more code...
}
This has been verified with #MaximYegorushkin's sample main.
int main() {
char** p = 0;
perform_work_on_a_range(p, p);
long* q = 0;
perform_work_on_a_range(q, q);
}
Output:
si
You probably want to do something like this instead:
template <typename T>
void do_something_type_specific() {}
template <>
void do_something_type_specific<int>() {...}
template <typename Iterator>
void perform_work_on_a_range(Iterator begin, Iterator end) {
do_something_type_specific<typename Iterator::value_type>();
}

Translating a std::tuple into a template parameter pack

I have a
typedef std::tuple<A, B> TupleType;
and would like to use the list of classes
for a "template".
Suppose I have:
template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}
and that I can successfully use it with:
auto my_tuple = parse<A, B>(ifs);
is it possible to avoid having to specify the class list A,B if I already have a
typedef std::tuple<A,B> TupleType;
where the list A,B is already present?
an example:
#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE
#include <iostream> // std::cerr
#include <fstream> // std::ifstream
#include <tuple> // std::tuple
class A {
public:
A(std::istream &); // May throw FooBaarException
};
class B {
public:
B(std::istream &); // May throw FooBaarException
};
template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}
int main() {
std::ifstream ifs;
ifs.exceptions(ifstream::eofbit | ifstream::failbit | ifstream::badbit);
int res = EXIT_FAILURE;
try {
ifs.open("/some/file/path", std::ios::in | std::ios::binary);
auto my_tuple = parse<A, B>(ifs); // my_tuple is of the type std::tuple<A,B>
/* Here do something interesting with my_tuple */
res = EXIT_SUCCESS;
} catch (ifstream::failure e) {
std::cerr << "error: opening or reading file failed\n";
} catch (FooBaarException e) {
std::cerr << "error: parsing in a constructor failed\n";
}
return res;
}
The underlying problem in your situation seems to be that you'd like to specialize the function template parse for the special case when the template argument is a std::tuple. Unfortunately, this kind of specialization isn't possible with function templates.
However, it is possible with class templates.
So, as a first step, you could define parse as a static function of a struct, like this:
using std::istream;
using std::tuple;
using std::make_tuple;
struct A { A(const istream &) {} };
struct B { B(const istream &) {} };
template <typename... Args>
struct parser
{
/* Your original function, now inside a struct.
I'm using direct tuple construction and an
initializer list to circumvent the order-of-
construction problem mentioned in the comment
to your question. */
static tuple<Args...> parse(const istream &strm)
{ return tuple<Args...> {Args(strm)...}; }
};
template <typename... Args>
struct parser<tuple<Args...>>
{
/* Specialized for tuple. */
static tuple<Args...> parse(const istream &strm)
{ return parser<Args...>::parse(strm); }
};
You can then call it in the desired way:
int main()
{
typedef tuple<A,B> tuple_type;
auto tup = parser<tuple_type>::parse(std::cin);
return 0;
}
As a second step, you can define a function template (again) which passes the arguments on to the right specialization of the struct:
template <typename... Args>
auto parse(const istream &strm) -> decltype(parser<Args...>::parse(strm))
{ return parser<Args...>::parse(strm); }
And now you can use it in exactly the way you wanted:
int main()
{
typedef tuple<A,B> tuple_type;
auto tup = parse<tuple_type>(std::cin);
return 0;
}
(And you can still use it in the old way, too: auto tup = parse<A,B>(std::cin).)
Remark. As mentioned in the comment to parser::parse(), I used direct tuple construction instead of make_tuple to avoid problems with the order of construction of the tuple elements. This is not directly related to your question, but a good thing to do. See how to avoid undefined execution order for the constructors when using std::make_tuple.
There is a standard idiom for this kind of thing. [1]
// Define the "shape" of the template
template<typename Tuple> struct TupleMap;
// Specialize it for std::tuple
template<typename...T> struct TupleMap<std::tuple<T...>> {
using type = std::tuple<T...>; // not necessary but saves typing
// ... inside here, you have access to the parameter pac
}
Here's an example of using it, which might or might not fit your expectations (your example doesn't really indicate your expected use, since it lacks the typedef you promise in your question): liveworkspace.org.
Since litb raised the point, it is possible to force the tuple-components to be constructed in left-to-right order, illustrating another interesting idiom: comb inheritance. See lws.
(Since lws might disappear again, who knows, I'll paste the code here as well):
#include <iostream>
#include <tuple>
#include <type_traits>
#include <utility>
// Define the "shape" of the template
template<typename Tuple> struct TupleMap;
// Specialize it for std::tuple
template<typename...T> struct TupleMap<std::tuple<T...>> {
using type = std::tuple<T...>; // not necessary but saves typing
type value;
template<typename Arg>
TupleMap(Arg&& arg)
: value(T(std::forward<Arg>(arg))...) {
}
operator type() { return value; }
};
//Try it out:
using std::get; // Note 2
using Numbers = std::tuple<char, double, int>;
// Note 3
std::ostream& operator<<(std::ostream& out, const Numbers& n) {
return out << get<0>(n) << ' ' << get<1>(n) << ' ' << get<2>(n);
}
int main() {
std::cout << TupleMap<Numbers>(93.14159);
return 0;
}
[1] At least, I think it's a standard idiom. I use it a lot, and think of it as the "can-opener" pattern.
[2] This is needed (or at least, it's my style) to allow the use of get with tuple-like templates defined outside of std. Doing it this way allows ADL to find the appropriate definition of get without forcing me to add specializations to std::get. In this way, it's similar to the standard ADL idiom for begin and end.
[3] You can search SO for a cool hack to specialize operator<< for all tuples. There's a simpler one which can be used for specific tuples, but that's all off-topic for this question, so I just did something easy and dependency free. Note that this works because of the conversion operator in TupleMap
The basic approach is to create a sequence of indices 0, ..., std::tuple_size<Tuple>::value - 1 as a parameter pack Indices and call your function with parse<typename std::tuple_element<Tuple, Indices>::type...>(stream). You'd probably encapsulate the logic into a function parse_tuple<Tuple>(stream) (and some function this one delegates to) which in the end delegates to parse<...>(stream).
First, here is a class template and a function to create a sequence of indices based on the size of a std::tuple. The indices are needed to obtain a list of type from std::tuple:
template <int... Indices> struct indices;
template <>
struct indices<-1> { // for an empty std::tuple<> there is no entry
typedef indices<> type;
};
template <int... Indices>
struct indices<0, Indices...> { // stop the recursion when 0 is reached
typedef indices<0, Indices...> type;
};
template <int Index, int... Indices>
struct indices<Index, Indices...> { // recursively build a sequence of indices
typedef typename indices<Index - 1, Index, Indices...>::type type;
};
template <typename T>
typename indices<std::tuple_size<T>::value - 1>::type const*
make_indices() {
return 0;
}
With this in place, it is quite easy to extract the sequence of types from a std::tuple<T...>:
template<typename T, int... Indices>
T parse_tuple(std::istream &stream, indices<Indices...> const*) {
return parse<typename std::tuple_element<Indices, T>::type...>(stream);
}
template <typename T>
T parse_tuple(std::istream& stream) {
return parse_tuple<T>(stream, make_indices<T>());
}

Is it possible to iterate an mpl::vector at run time without instantiating the types in the vector?

Generally, I would use boost::mpl::for_each<>() to traverse a boost::mpl::vector, but this requires a functor with a template function declared like the following:
template<typename T> void operator()(T&){T::staticCall();}
My problem with this is that I don't want the object T to be instantiated by for_each<>. I don't need the T parameter in the operator() at all. Is there a way to accomplish this, or an alternative to for_each<> that doesn't pass an object of type T to the template function?
Optimally, I would like the operator() definition to look like this:
template<typename T> void operator()(){T::staticCall();}
And of course, I don't want T to be instantiated at all prior to the call. Any other tips/suggestions are also welcome.
Just encountered the same situation and provided different solution to the problem which I would like to share. It's not as that obvious, but it uses an existing algorithm. The idea is to use pointers instead.
typedef boost::mpl::vector<type1*, type2*> container;
struct functor
{
template<typename T> void operator()(T*)
{
std::cout << "created " << typeid(T).name() << std::endl;
}
};
int main()
{
boost::mpl::for_each<container>(functor());
}
so here we get a null pointers, but we don't care as we are not going to use them.
As I stated before that is not obvious in the code and would probably require some additional comments, but it still solves the question without writing any additional code.
added
I think Diego Sevilla suggested something similar.
Interesting question! As far as I can tell, Boost.MPL does not seem to provide such an algorithm. However, writing your own should not be too difficult using iterators.
Here is a possible solution:
#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/next_prior.hpp>
#include <boost/mpl/vector.hpp>
using namespace boost::mpl;
namespace detail {
template < typename Begin, typename End, typename F >
struct static_for_each
{
static void call( )
{
typedef typename Begin::type currentType;
F::template call< currentType >();
static_for_each< typename next< Begin >::type, End, F >::call();
}
};
template < typename End, typename F >
struct static_for_each< End, End, F >
{
static void call( )
{
}
};
} // namespace detail
template < typename Sequence, typename F >
void static_for_each( )
{
typedef typename begin< Sequence >::type begin;
typedef typename end< Sequence >::type end;
detail::static_for_each< begin, end, F >::call();
}
[The naming may not be very well chosen, but well...]
Here is how you would use this algorithm:
struct Foo
{
static void staticMemberFunction( )
{
std::cout << "Foo";
}
};
struct Bar
{
static void staticMemberFunction( )
{
std::cout << "Bar";
}
};
struct CallStaticMemberFunction
{
template < typename T >
static void call()
{
T::staticMemberFunction();
}
};
int main()
{
typedef vector< Foo, Bar > sequence;
static_for_each< sequence, CallStaticMemberFunction >(); // prints "FooBar"
}
Well, first of all, the static call in your code means that your object will exist. Before/after is meaningless in that regard. The only time, "I don't want T to be instantiated at all prior to the call," make sense is when T is a template. It's not, because it can't be. It is true that it is that line that causes the object to exist, but I am pretty sure it won't just exist there once the product is compiled.
Second of all, I don't believe that there's a current method to use for_each without instantiating. IMHO this is a bug in MPL caused by a questionable decision to use operator(). Won't say it's wrong since I know the developer and he's a lot smarter than I am, but it seems so from here now that you bring this up.
So, I think you're stuck having to remake a for_each that calls a templated function that doesn't require the parameter. I'm almost certain it is possible, but also equally certain it's not readily available as a premade component in MPL.
Marcin, you're very right. I've been thinking this along and I don't see an easy solution for this. Even if you cannot write the empty operator(), it would be at least possible to use a pointer, that doesn't need an actual object to exist. You have to roll your own implementation, it seems.
Here is an alternative solution highly inspired from Luc Touraille's answer.
This version is done using Metafunction classes instead of functions which allows the static_for_each to be called even outside of function scopes (useful if the job has to be totally done at compiletime so you have no unnecessary functions called at runtime).
Furthermore it gives more interaction thanks to the first and last typedefs, allowing to get information out of the loop if necessary, a little like the way a return works for a function.
You can also access the previous iteration result within each iteration thanks to the second template parameter Previous passed to the metafunction class F.
Finally you can provide data to the loop process using the Initial template parameter, it will be given as the value of the Previous parameter of the first iteration.
# include <boost/mpl/begin_end.hpp>
# include <boost/mpl/next_prior.hpp>
# include <boost/mpl/apply.hpp>
namespace detail_static_for_each
{
// Loop
template<typename Begin, typename End, typename F, typename Previous>
struct static_for_each
{
private:
typedef typename Begin::type current_type;
public:
typedef typename boost::mpl::apply<F, current_type, Previous>::type first;
typedef typename static_for_each<typename boost::mpl::next<Begin>::type, End, F, first>::last last;
};
// End of loop
template<typename End, typename F, typename Last>
struct static_for_each<End, End, F, Last>
{
public:
typedef Last first;
typedef Last last;
};
} // namespace detail_static_for_each
// Public interface
template<typename Sequence, typename F, typename Initial = void>
struct static_for_each
{
private:
typedef typename boost::mpl::begin<Sequence>::type begin;
typedef typename boost::mpl::end<Sequence>::type end;
typedef typename detail_static_for_each::static_for_each<begin, end, F, Initial> loop;
public:
typedef typename loop::first first;
typedef typename loop::last last;
};
Here is a simple example that both gives and retrieves data :
# include <iostream>
# include <boost/type_traits/is_same.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/vector.hpp>
# include "static_for_each.hpp"
struct is_there_a_float
{
template<typename currentItem, typename PreviousIterationType>
struct apply
{
typedef typename boost::mpl::if_< PreviousIterationType,
PreviousIterationType,
boost::is_same<float, currentItem> >::type type;
};
};
struct test
{
typedef boost::mpl::vector< char, long, long, double, float, int, char > sequence;
typedef static_for_each<sequence, is_there_a_float, boost::false_type>::last found;
};
int main(void)
{
std::cout << std::boolalpha << test::found::value << std::endl;
return (0);
}
These features makes the use of static_for_each more similar to the use of common runtime loops (while, for, BOOST_FOREACH ...) as you can interact more directly with the loop.
I liked (up-voted) the solution with pointer and own defined *_for_each function. Here is an alternative using type wrapper for T if the goal is to avoid object creation till it is needed.
template<typename T>
struct Wrapper
{
typedef T type;
};
struct Functor
{
template<typename T> void operator()(T t)
{
T::type obj(1);
T::type::static_fuc();
}
};
struct T1
{
T1(int a) : m_a(a) { }
int m_a;
static inline void static_fuc() { }
};
struct T2
{
T2(int a) : m_a(a) { }
int m_a;
static inline void static_fuc() { }
};
void fun()
{
namespace mpl=boost::mpl;
typedef mpl::vector<Wrapper<T1>,Wrapper<T2> > t_vec;
mpl::for_each<t_vec>(Functor());
}