1

I have a std::tuple (or a boost fusion tuple) whose elements cannot be trivially constructed (for example references) and I want to iterate over the types but not the values of the elements.

In this example I have a (general) tuple type and I want to generate a vector with (runtime) type information. The example below works if all the types in the sequence are trivially default constructed but not in general.

In summary, I want a function that transform: std::tuple<...> -> std::vector<std::type_index>

#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <typeindex>
#include<vector>

using tuple_type = std::tuple<std::string&, int>;

int main(){
    std::vector<std::type_index> types;
    boost::fusion::for_each(
        tuple_type{},  // fails because of std::string&
        [&types](auto& e){types.push_back(typeid(e));} 
    ); 
}

The problem is that I have to generate runtime information from non runtime information and I can't figure out how to mix the fusion functions (http://www.boost.org/doc/libs/1_59_0/libs/fusion/doc/html/fusion/algorithm/iteration/functions.html) and the metafunctions (http://www.boost.org/doc/libs/1_41_0/libs/fusion/doc/html/fusion/algorithm/iteration/metafunctions.html).

I tried with boost::fusion::accumulate and boost::fold but the situation is always the same, at some point I have to generate a runtime element in order to apply the algorithm.


EDIT: I solved the original problem (std::tuple<...> -> std::vector<std::type_index>). I can't imagine another context at the moment but maybe the fundamental question still stands.

I did it by using a trick involving expanding a parameter pack over the typeid function in the constructor of std::vector (or std::array).

template<class... Args>
std::array<std::type_index, sizeof...(Args)> const& types_info<std::tuple<Args...>>::value{typeid(Args)...};

The complete code is this (note that I also decided to use std::array).

#include <typeindex>
#include<array>
#include<iostream>

template<class T>
struct types_info;

template<class... Args>
struct types_info<std::tuple<Args...>>{
    static std::array<std::type_index, sizeof...(Args)> const& value;//{typeid(Args)...};
};

template<class... Args>
std::array<std::type_index, sizeof...(Args)> const& types_info<std::tuple<Args...>>::value{typeid(Args)...};

// vvv works only in C++1z
template<template<typename...> typename T, class... Args> // non tuples types as well
struct types_info<T<Args...>> : types_info<std::tuple<Args...>>{};

using tuple_type = std::tuple<std::string&, int>;

int main(){

    std::vector<std::type_index> types;

    std::cout << types_info<tuple_type>::value.size() << std::endl;
    std::cout << types_info<std::map<int, std::string>>::value.size() << std::endl;
}
alfC
  • 14,261
  • 4
  • 67
  • 118
  • 1
    [This question](http://stackoverflow.com/questions/27719483/how-do-i-loop-over-a-boost-mpl-list-of-non-default-constructed-classes) is similar (I think `mpl::for_each` is more appropriate). [Here](http://coliru.stacked-crooked.com/a/992de02dc33faf75) is something based on that question, the lambda is absolutely horrible and I don't know enough about `typeid` to know whether the loss of the reference is normal or I made some mistake. – llonesmiz Nov 30 '15 at 08:43
  • 1
    @cv_and_he , interesting that the other example also wants it to generate a container of type_info (it seems that this is the only context where this question makes sense, which I solved in a completely different way). `typeid` should preserve the reference information, I don't know why your code misses the reference information (checked also with `clang 3.5`) the reference information is lost somewhere in the `typename decltype(e)::type` acrobatics. – alfC Nov 30 '15 at 08:55
  • [Maybe it's just the `.name()` that removes the reference (I really have no idea)](http://coliru.stacked-crooked.com/a/623afcfc1627a1cc). – llonesmiz Nov 30 '15 at 09:07
  • @cv_and_he, sorry, my fault, `typeid` does removes reference information (it is required to). – alfC Nov 30 '15 at 16:20
  • If you need to keep that information, [Boost.TypeIndex seems to be able to deal with it](http://www.boost.org/doc/html/boost/typeindex/type_id_with_cvr.html). – llonesmiz Nov 30 '15 at 17:02
  • @cv_and_he, yes, I am looking into that. The problem is in my solution I can't make `boost::typeindex::type_id_with_cvr()...` (paramater pack) expand. I will try to combine your solution with Boost.Typeindex. – alfC Nov 30 '15 at 17:57
  • 1
    [This](http://coliru.stacked-crooked.com/a/0396f6d5c05e9188) seems to work. – llonesmiz Nov 30 '15 at 18:31

0 Answers0